@zenithbuild/core 0.1.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/.eslintignore +15 -0
- package/.gitattributes +2 -0
- package/.github/ISSUE_TEMPLATE/compiler-errors-for-invalid-state-declarations.md +25 -0
- package/.github/ISSUE_TEMPLATE/new_ticket.yaml +34 -0
- package/.github/pull_request_template.md +15 -0
- package/.github/workflows/discord-changelog.yml +141 -0
- package/.github/workflows/discord-notify.yml +242 -0
- package/.github/workflows/discord-version.yml +195 -0
- package/.prettierignore +13 -0
- package/.prettierrc +21 -0
- package/.zen.d.ts +15 -0
- package/LICENSE +21 -0
- package/README.md +55 -0
- package/app/components/Button.zen +46 -0
- package/app/components/Link.zen +11 -0
- package/app/favicon.ico +0 -0
- package/app/layouts/Main.zen +59 -0
- package/app/pages/about.zen +23 -0
- package/app/pages/blog/[id].zen +53 -0
- package/app/pages/blog/index.zen +32 -0
- package/app/pages/dynamic-dx.zen +712 -0
- package/app/pages/dynamic-primitives.zen +453 -0
- package/app/pages/index.zen +154 -0
- package/app/pages/navigation-demo.zen +229 -0
- package/app/pages/posts/[...slug].zen +61 -0
- package/app/pages/primitives-demo.zen +273 -0
- package/assets/logos/0E3B5DDD-605C-4839-BB2E-DFCA8ADC9604.PNG +0 -0
- package/assets/logos/760971E5-79A1-44F9-90B9-925DF30F4278.PNG +0 -0
- package/assets/logos/8A06ED80-9ED2-4689-BCBD-13B2E95EE8E4.JPG +0 -0
- package/assets/logos/C691FF58-ED13-4E8D-B6A3-02E835849340.PNG +0 -0
- package/assets/logos/C691FF58-ED13-4E8D-B6A3-02E835849340.svg +601 -0
- package/assets/logos/README.md +54 -0
- package/assets/logos/zen.icns +0 -0
- package/bun.lock +39 -0
- package/compiler/README.md +380 -0
- package/compiler/errors/compilerError.ts +24 -0
- package/compiler/finalize/finalizeOutput.ts +163 -0
- package/compiler/finalize/generateFinalBundle.ts +82 -0
- package/compiler/index.ts +44 -0
- package/compiler/ir/types.ts +83 -0
- package/compiler/legacy/binding.ts +254 -0
- package/compiler/legacy/bindings.ts +338 -0
- package/compiler/legacy/component-process.ts +1208 -0
- package/compiler/legacy/component.ts +301 -0
- package/compiler/legacy/event.ts +50 -0
- package/compiler/legacy/expression.ts +1149 -0
- package/compiler/legacy/mutation.ts +280 -0
- package/compiler/legacy/parse.ts +299 -0
- package/compiler/legacy/split.ts +608 -0
- package/compiler/legacy/types.ts +32 -0
- package/compiler/output/types.ts +34 -0
- package/compiler/parse/detectMapExpressions.ts +102 -0
- package/compiler/parse/parseScript.ts +22 -0
- package/compiler/parse/parseTemplate.ts +425 -0
- package/compiler/parse/parseZenFile.ts +66 -0
- package/compiler/parse/trackLoopContext.ts +82 -0
- package/compiler/runtime/dataExposure.ts +291 -0
- package/compiler/runtime/generateDOM.ts +144 -0
- package/compiler/runtime/generateHydrationBundle.ts +383 -0
- package/compiler/runtime/hydration.ts +309 -0
- package/compiler/runtime/navigation.ts +432 -0
- package/compiler/runtime/thinRuntime.ts +160 -0
- package/compiler/runtime/transformIR.ts +256 -0
- package/compiler/runtime/wrapExpression.ts +84 -0
- package/compiler/runtime/wrapExpressionWithLoop.ts +77 -0
- package/compiler/spa-build.ts +1000 -0
- package/compiler/test/validate-test.ts +104 -0
- package/compiler/transform/generateBindings.ts +47 -0
- package/compiler/transform/generateHTML.ts +28 -0
- package/compiler/transform/transformNode.ts +126 -0
- package/compiler/transform/transformTemplate.ts +38 -0
- package/compiler/validate/validateExpressions.ts +168 -0
- package/core/index.ts +135 -0
- package/core/lifecycle/index.ts +49 -0
- package/core/lifecycle/zen-mount.ts +182 -0
- package/core/lifecycle/zen-unmount.ts +88 -0
- package/core/reactivity/index.ts +54 -0
- package/core/reactivity/tracking.ts +167 -0
- package/core/reactivity/zen-batch.ts +57 -0
- package/core/reactivity/zen-effect.ts +139 -0
- package/core/reactivity/zen-memo.ts +146 -0
- package/core/reactivity/zen-ref.ts +52 -0
- package/core/reactivity/zen-signal.ts +121 -0
- package/core/reactivity/zen-state.ts +180 -0
- package/core/reactivity/zen-untrack.ts +44 -0
- package/docs/COMMENTS.md +111 -0
- package/docs/COMMITS.md +36 -0
- package/docs/CONTRIBUTING.md +116 -0
- package/docs/STYLEGUIDE.md +62 -0
- package/package.json +44 -0
- package/router/index.ts +76 -0
- package/router/manifest.ts +314 -0
- package/router/navigation/ZenLink.zen +231 -0
- package/router/navigation/index.ts +78 -0
- package/router/navigation/zen-link.ts +584 -0
- package/router/runtime.ts +458 -0
- package/router/types.ts +168 -0
- package/runtime/build.ts +17 -0
- package/runtime/serve.ts +93 -0
- package/scripts/webhook-proxy.ts +213 -0
- package/tsconfig.json +28 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
// ============================================
|
|
3
|
+
// Dynamic HTML - Primitives-Driven Demo
|
|
4
|
+
// ============================================
|
|
5
|
+
|
|
6
|
+
// State declarations
|
|
7
|
+
state isLoggedIn = false
|
|
8
|
+
state isLoading = false
|
|
9
|
+
state count = 0
|
|
10
|
+
state username = "Guest"
|
|
11
|
+
|
|
12
|
+
// Array state for map iterations
|
|
13
|
+
state users = [
|
|
14
|
+
{ id: 1, name: "Alice", role: "Admin" },
|
|
15
|
+
{ id: 2, name: "Bob", role: "Editor" },
|
|
16
|
+
{ id: 3, name: "Charlie", role: "Viewer" }
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
// Event handlers (all functions below are used in onclick handlers)
|
|
20
|
+
function toggleLogin() {
|
|
21
|
+
isLoggedIn = !isLoggedIn
|
|
22
|
+
username = isLoggedIn ? "John Doe" : "Guest"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function toggleLoading() {
|
|
26
|
+
isLoading = !isLoading
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function increment() {
|
|
30
|
+
count = count + 1
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function decrement() {
|
|
34
|
+
count = count - 1
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function addUser() {
|
|
38
|
+
const newId = users.length + 1
|
|
39
|
+
users = [...users, { id: newId, name: "User " + newId, role: "Viewer" }]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function removeLastUser() {
|
|
43
|
+
if (users.length > 0) {
|
|
44
|
+
users = users.slice(0, -1)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<style>
|
|
50
|
+
/* Reset and full-page container */
|
|
51
|
+
.primitives-page {
|
|
52
|
+
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
|
|
53
|
+
background: linear-gradient(180deg, #0f172a 0%, #1e293b 100%);
|
|
54
|
+
min-height: 100vh;
|
|
55
|
+
color: #e2e8f0;
|
|
56
|
+
padding: 0;
|
|
57
|
+
margin: 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.primitives-container {
|
|
61
|
+
max-width: 900px;
|
|
62
|
+
margin: 0 auto;
|
|
63
|
+
padding: 40px 24px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Header */
|
|
67
|
+
.page-header {
|
|
68
|
+
text-align: center;
|
|
69
|
+
margin-bottom: 48px;
|
|
70
|
+
padding: 40px 32px;
|
|
71
|
+
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
|
72
|
+
border-radius: 20px;
|
|
73
|
+
box-shadow: 0 8px 32px rgba(99, 102, 241, 0.3);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.page-header h1 {
|
|
77
|
+
margin: 0 0 12px 0;
|
|
78
|
+
font-size: 2.5rem;
|
|
79
|
+
font-weight: 800;
|
|
80
|
+
color: white;
|
|
81
|
+
letter-spacing: -0.02em;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.page-header p {
|
|
85
|
+
margin: 0;
|
|
86
|
+
color: rgba(255,255,255,0.9);
|
|
87
|
+
font-size: 1.1rem;
|
|
88
|
+
font-weight: 500;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* Sections */
|
|
92
|
+
.demo-section {
|
|
93
|
+
background: #1e293b;
|
|
94
|
+
border: 1px solid #334155;
|
|
95
|
+
border-radius: 16px;
|
|
96
|
+
padding: 28px;
|
|
97
|
+
margin-bottom: 28px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.demo-section h2 {
|
|
101
|
+
margin: 0 0 8px 0;
|
|
102
|
+
color: #a5b4fc;
|
|
103
|
+
font-size: 1.25rem;
|
|
104
|
+
font-weight: 700;
|
|
105
|
+
display: flex;
|
|
106
|
+
align-items: center;
|
|
107
|
+
gap: 10px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.section-description {
|
|
111
|
+
color: #94a3b8;
|
|
112
|
+
margin: 0 0 20px 0;
|
|
113
|
+
font-size: 0.95rem;
|
|
114
|
+
line-height: 1.5;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.demo-area {
|
|
118
|
+
background: #0f172a;
|
|
119
|
+
border-radius: 12px;
|
|
120
|
+
padding: 24px;
|
|
121
|
+
margin-bottom: 20px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Buttons */
|
|
125
|
+
.btn {
|
|
126
|
+
background: #6366f1;
|
|
127
|
+
color: white;
|
|
128
|
+
border: none;
|
|
129
|
+
border-radius: 10px;
|
|
130
|
+
padding: 12px 24px;
|
|
131
|
+
cursor: pointer;
|
|
132
|
+
font-size: 14px;
|
|
133
|
+
font-family: inherit;
|
|
134
|
+
font-weight: 600;
|
|
135
|
+
transition: all 0.2s ease;
|
|
136
|
+
margin: 4px;
|
|
137
|
+
display: inline-flex;
|
|
138
|
+
align-items: center;
|
|
139
|
+
gap: 8px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.btn:hover {
|
|
143
|
+
background: #4f46e5;
|
|
144
|
+
transform: translateY(-2px);
|
|
145
|
+
box-shadow: 0 6px 20px rgba(99, 102, 241, 0.4);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.btn-secondary {
|
|
149
|
+
background: #475569;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.btn-secondary:hover {
|
|
153
|
+
background: #334155;
|
|
154
|
+
box-shadow: 0 6px 20px rgba(71, 85, 105, 0.4);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.btn-success {
|
|
158
|
+
background: #22c55e;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.btn-success:hover {
|
|
162
|
+
background: #16a34a;
|
|
163
|
+
box-shadow: 0 6px 20px rgba(34, 197, 94, 0.4);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.btn-danger {
|
|
167
|
+
background: #ef4444;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.btn-danger:hover {
|
|
171
|
+
background: #dc2626;
|
|
172
|
+
box-shadow: 0 6px 20px rgba(239, 68, 68, 0.4);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Status badges */
|
|
176
|
+
.status-badge {
|
|
177
|
+
display: inline-block;
|
|
178
|
+
padding: 6px 16px;
|
|
179
|
+
border-radius: 20px;
|
|
180
|
+
font-size: 13px;
|
|
181
|
+
font-weight: 600;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.status-active {
|
|
185
|
+
background: rgba(34, 197, 94, 0.15);
|
|
186
|
+
color: #4ade80;
|
|
187
|
+
border: 1px solid rgba(34, 197, 94, 0.3);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.status-inactive {
|
|
191
|
+
background: rgba(239, 68, 68, 0.15);
|
|
192
|
+
color: #f87171;
|
|
193
|
+
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Flex helpers */
|
|
197
|
+
.flex-row {
|
|
198
|
+
display: flex;
|
|
199
|
+
align-items: center;
|
|
200
|
+
gap: 16px;
|
|
201
|
+
flex-wrap: wrap;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.flex-center {
|
|
205
|
+
display: flex;
|
|
206
|
+
justify-content: center;
|
|
207
|
+
align-items: center;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* Counter */
|
|
211
|
+
.counter-display {
|
|
212
|
+
font-size: 4rem;
|
|
213
|
+
font-weight: 800;
|
|
214
|
+
color: #6366f1;
|
|
215
|
+
text-align: center;
|
|
216
|
+
padding: 32px;
|
|
217
|
+
background: linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%);
|
|
218
|
+
border-radius: 16px;
|
|
219
|
+
margin-bottom: 20px;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/* Messages */
|
|
223
|
+
.welcome-message {
|
|
224
|
+
color: #4ade80;
|
|
225
|
+
padding: 16px 20px;
|
|
226
|
+
background: rgba(34, 197, 94, 0.1);
|
|
227
|
+
border-radius: 10px;
|
|
228
|
+
border-left: 4px solid #22c55e;
|
|
229
|
+
font-weight: 500;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.login-prompt {
|
|
233
|
+
color: #fbbf24;
|
|
234
|
+
padding: 16px 20px;
|
|
235
|
+
background: rgba(245, 158, 11, 0.1);
|
|
236
|
+
border-radius: 10px;
|
|
237
|
+
border-left: 4px solid #f59e0b;
|
|
238
|
+
font-weight: 500;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* User list */
|
|
242
|
+
.user-list-container {
|
|
243
|
+
margin-top: 16px;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.user-count {
|
|
247
|
+
padding: 16px 20px;
|
|
248
|
+
background: rgba(99, 102, 241, 0.1);
|
|
249
|
+
border-radius: 10px;
|
|
250
|
+
color: #a5b4fc;
|
|
251
|
+
font-weight: 600;
|
|
252
|
+
text-align: center;
|
|
253
|
+
font-size: 1.1rem;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/* Code blocks */
|
|
257
|
+
.code-section {
|
|
258
|
+
margin-top: 20px;
|
|
259
|
+
padding-top: 20px;
|
|
260
|
+
border-top: 1px solid #334155;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.code-section h3 {
|
|
264
|
+
margin: 0 0 12px 0;
|
|
265
|
+
color: #64748b;
|
|
266
|
+
font-size: 0.85rem;
|
|
267
|
+
font-weight: 600;
|
|
268
|
+
text-transform: uppercase;
|
|
269
|
+
letter-spacing: 0.05em;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.code-block {
|
|
273
|
+
background: #0f172a;
|
|
274
|
+
border: 1px solid #334155;
|
|
275
|
+
border-radius: 10px;
|
|
276
|
+
padding: 16px 20px;
|
|
277
|
+
font-family: 'Fira Code', 'Consolas', monospace;
|
|
278
|
+
font-size: 13px;
|
|
279
|
+
overflow-x: auto;
|
|
280
|
+
color: #94a3b8;
|
|
281
|
+
line-height: 1.6;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.code-keyword {
|
|
285
|
+
color: #c084fc;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.code-string {
|
|
289
|
+
color: #34d399;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.code-comment {
|
|
293
|
+
color: #475569;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Navigation */
|
|
297
|
+
.nav-section {
|
|
298
|
+
display: flex;
|
|
299
|
+
gap: 12px;
|
|
300
|
+
flex-wrap: wrap;
|
|
301
|
+
justify-content: center;
|
|
302
|
+
padding-top: 20px;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.nav-link {
|
|
306
|
+
display: inline-flex;
|
|
307
|
+
align-items: center;
|
|
308
|
+
gap: 8px;
|
|
309
|
+
padding: 14px 28px;
|
|
310
|
+
background: #334155;
|
|
311
|
+
color: white;
|
|
312
|
+
text-decoration: none;
|
|
313
|
+
border-radius: 12px;
|
|
314
|
+
font-weight: 600;
|
|
315
|
+
transition: all 0.2s ease;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.nav-link:hover {
|
|
319
|
+
background: #475569;
|
|
320
|
+
transform: translateY(-2px);
|
|
321
|
+
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
|
322
|
+
}
|
|
323
|
+
</style>
|
|
324
|
+
|
|
325
|
+
<Main title="Dynamic HTML - Primitives">
|
|
326
|
+
<div class="primitives-page">
|
|
327
|
+
<div class="primitives-container">
|
|
328
|
+
<header class="page-header">
|
|
329
|
+
<h1>⚡ Dynamic HTML Rendering</h1>
|
|
330
|
+
<p>Primitives-Driven Approach — Explicit Control</p>
|
|
331
|
+
</header>
|
|
332
|
+
|
|
333
|
+
<section class="demo-section">
|
|
334
|
+
<h2>🔀 Static Conditionals</h2>
|
|
335
|
+
<p class="section-description">
|
|
336
|
+
Use <code>condition && element</code> for conditional rendering based on state.
|
|
337
|
+
</p>
|
|
338
|
+
|
|
339
|
+
<div class="demo-area">
|
|
340
|
+
<div class="flex-row" style="margin-bottom: 20px;">
|
|
341
|
+
<button class="btn" onclick="toggleLogin">Toggle Login Status</button>
|
|
342
|
+
<span class="status-badge" :class="isLoggedIn ? 'status-active' : 'status-inactive'">
|
|
343
|
+
{isLoggedIn ? "✓ Logged In" : "✕ Logged Out"}
|
|
344
|
+
</span>
|
|
345
|
+
</div>
|
|
346
|
+
|
|
347
|
+
<div>
|
|
348
|
+
{isLoggedIn && <div class="welcome-message">✓ Welcome back, {username}!</div>}
|
|
349
|
+
{!isLoggedIn && <div class="login-prompt">⚠ Please log in to continue</div>}
|
|
350
|
+
</div>
|
|
351
|
+
</div>
|
|
352
|
+
|
|
353
|
+
<div class="code-section">
|
|
354
|
+
<h3>Code Example</h3>
|
|
355
|
+
<pre class="code-block"><span class="code-comment">// State declaration</span>
|
|
356
|
+
<span class="code-keyword">state</span> isLoggedIn = <span class="code-keyword">false</span>
|
|
357
|
+
|
|
358
|
+
<span class="code-comment">// Conditional rendering</span>
|
|
359
|
+
{isLoggedIn && <span>Welcome back!</span>}
|
|
360
|
+
{!isLoggedIn && <span>Please log in</span>}</pre>
|
|
361
|
+
</div>
|
|
362
|
+
</section>
|
|
363
|
+
|
|
364
|
+
<section class="demo-section">
|
|
365
|
+
<h2>❓ Inline Ternaries</h2>
|
|
366
|
+
<p class="section-description">
|
|
367
|
+
Use <code>condition ? A : B</code> for inline conditional content that switches between two values.
|
|
368
|
+
</p>
|
|
369
|
+
|
|
370
|
+
<div class="demo-area">
|
|
371
|
+
<div class="flex-row" style="margin-bottom: 20px;">
|
|
372
|
+
<button class="btn" onclick="toggleLoading">Toggle Loading State</button>
|
|
373
|
+
</div>
|
|
374
|
+
|
|
375
|
+
<button class="btn" :class="isLoading ? 'btn-secondary' : 'btn-success'" style="font-size: 16px; padding: 16px 32px;">
|
|
376
|
+
{isLoading ? "⏳ Loading..." : "✓ Submit"}
|
|
377
|
+
</button>
|
|
378
|
+
</div>
|
|
379
|
+
|
|
380
|
+
<div class="code-section">
|
|
381
|
+
<h3>Code Example</h3>
|
|
382
|
+
<pre class="code-block"><span class="code-keyword">state</span> isLoading = <span class="code-keyword">false</span>
|
|
383
|
+
|
|
384
|
+
<button>
|
|
385
|
+
{isLoading ? <span class="code-string">"Loading..."</span> : <span class="code-string">"Submit"</span>}
|
|
386
|
+
</button></pre>
|
|
387
|
+
</div>
|
|
388
|
+
</section>
|
|
389
|
+
|
|
390
|
+
<section class="demo-section">
|
|
391
|
+
<h2>🔢 Counter with Dynamic Attributes</h2>
|
|
392
|
+
<p class="section-description">
|
|
393
|
+
Demonstrates how state changes update both text content and dynamic class bindings.
|
|
394
|
+
</p>
|
|
395
|
+
|
|
396
|
+
<div class="demo-area">
|
|
397
|
+
<div class="counter-display">{count}</div>
|
|
398
|
+
|
|
399
|
+
<div class="flex-center" style="margin-bottom: 20px;">
|
|
400
|
+
<button class="btn btn-secondary" onclick="decrement">− Decrement</button>
|
|
401
|
+
<button class="btn" onclick="increment">+ Increment</button>
|
|
402
|
+
</div>
|
|
403
|
+
|
|
404
|
+
<div class="flex-center">
|
|
405
|
+
<span class="status-badge" :class="count > 0 ? 'status-active' : 'status-inactive'">
|
|
406
|
+
{count > 0 ? "Positive" : "Zero or Negative"}
|
|
407
|
+
</span>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
</section>
|
|
411
|
+
|
|
412
|
+
<section class="demo-section">
|
|
413
|
+
<h2>📋 Array Operations</h2>
|
|
414
|
+
<p class="section-description">
|
|
415
|
+
Demonstrates dynamic state with arrays. The count updates reactively when users are added or removed.
|
|
416
|
+
</p>
|
|
417
|
+
|
|
418
|
+
<div class="demo-area">
|
|
419
|
+
<div class="flex-row" style="margin-bottom: 20px;">
|
|
420
|
+
<button class="btn btn-success" onclick="addUser">+ Add User</button>
|
|
421
|
+
<button class="btn btn-danger" onclick="removeLastUser">− Remove Last</button>
|
|
422
|
+
</div>
|
|
423
|
+
|
|
424
|
+
<div class="user-list-container">
|
|
425
|
+
<div class="user-count">
|
|
426
|
+
👥 Total Users: {users.length}
|
|
427
|
+
</div>
|
|
428
|
+
</div>
|
|
429
|
+
</div>
|
|
430
|
+
|
|
431
|
+
<div class="code-section">
|
|
432
|
+
<h3>Code Example</h3>
|
|
433
|
+
<pre class="code-block"><span class="code-keyword">state</span> users = [
|
|
434
|
+
{ id: 1, name: <span class="code-string">"Alice"</span> },
|
|
435
|
+
{ id: 2, name: <span class="code-string">"Bob"</span> }
|
|
436
|
+
]
|
|
437
|
+
|
|
438
|
+
<span class="code-comment">// Display count reactively</span>
|
|
439
|
+
Total: {users.length}</pre>
|
|
440
|
+
</div>
|
|
441
|
+
</section>
|
|
442
|
+
|
|
443
|
+
<section class="demo-section">
|
|
444
|
+
<h2>🔗 Navigation</h2>
|
|
445
|
+
<nav class="nav-section">
|
|
446
|
+
<ZenLink href="/" class="nav-link">← Home</ZenLink>
|
|
447
|
+
<ZenLink href="/dynamic-dx" class="nav-link">DX Demo →</ZenLink>
|
|
448
|
+
<ZenLink href="/primitives-demo" class="nav-link">Zen* API</ZenLink>
|
|
449
|
+
</nav>
|
|
450
|
+
</section>
|
|
451
|
+
</div>
|
|
452
|
+
</div>
|
|
453
|
+
</Main>
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
function parentCallback(clicks) {
|
|
3
|
+
console.log('Parent received clicks', clicks)
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function handleNavClick() {
|
|
7
|
+
console.log('[ZenLink] Navigation triggered via onClick handler')
|
|
8
|
+
}
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<style>
|
|
12
|
+
.zen-nav-link {
|
|
13
|
+
padding: 8px 16px;
|
|
14
|
+
background: #6366f1;
|
|
15
|
+
color: white;
|
|
16
|
+
text-decoration: none;
|
|
17
|
+
border-radius: 4px;
|
|
18
|
+
transition: background 0.2s, transform 0.1s;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.zen-nav-link:hover {
|
|
22
|
+
background: #4f46e5;
|
|
23
|
+
transform: translateY(-1px);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.zen-nav-link.zen-link-active {
|
|
27
|
+
background: #4338ca;
|
|
28
|
+
box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.legacy-link {
|
|
32
|
+
padding: 8px 16px;
|
|
33
|
+
background: #6b7280;
|
|
34
|
+
color: white;
|
|
35
|
+
text-decoration: none;
|
|
36
|
+
border-radius: 4px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.legacy-link:hover {
|
|
40
|
+
background: #4b5563;
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
43
|
+
|
|
44
|
+
<Main title="Home Page">
|
|
45
|
+
<div>
|
|
46
|
+
<h1>Zenith File-Based Router</h1>
|
|
47
|
+
<h2>Welcome to Zenith!</h2>
|
|
48
|
+
<p>This is the home page demonstrating file-based routing with SPA navigation.</p>
|
|
49
|
+
|
|
50
|
+
<div style="margin: 20px 0; padding: 20px; background: #e8f8e8; border-radius: 8px;">
|
|
51
|
+
<h3>🚀 Router Features</h3>
|
|
52
|
+
<ul>
|
|
53
|
+
<li>✅ File-based routing from <code>pages/</code> directory</li>
|
|
54
|
+
<li>✅ Dynamic routes with <code>[param]</code> syntax</li>
|
|
55
|
+
<li>✅ Catch-all routes with <code>[...slug]</code> syntax</li>
|
|
56
|
+
<li>✅ SPA navigation (no page reloads)</li>
|
|
57
|
+
<li>✅ Hard refresh works on any route</li>
|
|
58
|
+
<li>✅ Back/forward navigation works</li>
|
|
59
|
+
<li>✅ <strong>ZenLink component for SPA navigation</strong></li>
|
|
60
|
+
</ul>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<!-- ZenLink Navigation -->
|
|
64
|
+
<div style="margin: 20px 0; padding: 20px; border: 2px solid #6366f1; border-radius: 8px; background: #f0f0ff;">
|
|
65
|
+
<h3>🔗 ZenLink Navigation (SPA)</h3>
|
|
66
|
+
<p>These links use the <code><ZenLink></code> component for SPA-style navigation:</p>
|
|
67
|
+
<nav>
|
|
68
|
+
<ul style="list-style: none; padding: 0; display: flex; gap: 12px; flex-wrap: wrap;">
|
|
69
|
+
<li><ZenLink href="/" class="zen-nav-link" exact>Home</ZenLink></li>
|
|
70
|
+
<li><ZenLink href="/about" class="zen-nav-link">About</ZenLink></li>
|
|
71
|
+
<li><ZenLink href="/primitives-demo" class="zen-nav-link">Primitives Demo</ZenLink></li>
|
|
72
|
+
<li><ZenLink href="/navigation-demo" class="zen-nav-link">Navigation Demo</ZenLink></li>
|
|
73
|
+
<li><ZenLink href="/dynamic-dx" class="zen-nav-link">Dynamic Primitives</ZenLink></li>
|
|
74
|
+
<li><ZenLink href="/blog" class="zen-nav-link">Blog</ZenLink></li>
|
|
75
|
+
<li><ZenLink href="/blog/42" class="zen-nav-link" onClick="handleNavClick">Blog #42</ZenLink></li>
|
|
76
|
+
<li><ZenLink href="/posts/hello/world" class="zen-nav-link" preload>Catch-All</ZenLink></li>
|
|
77
|
+
</ul>
|
|
78
|
+
</nav>
|
|
79
|
+
<p style="font-size: 12px; color: #666; margin-top: 12px;">
|
|
80
|
+
✨ Features: Active state detection, onClick handlers, preload on hover
|
|
81
|
+
</p>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<!-- External Links -->
|
|
85
|
+
<div style="margin: 20px 0; padding: 20px; border: 1px solid #ccc; border-radius: 8px;">
|
|
86
|
+
<h3>🌐 External Links (via ZenLink)</h3>
|
|
87
|
+
<p>ZenLink automatically detects external URLs and opens them in new tabs:</p>
|
|
88
|
+
<nav>
|
|
89
|
+
<ul style="list-style: none; padding: 0; display: flex; gap: 12px; flex-wrap: wrap;">
|
|
90
|
+
<li><ZenLink href="https://github.com" target="_blank" class="zen-nav-link">GitHub</ZenLink></li>
|
|
91
|
+
<li><ZenLink href="https://bun.sh" class="zen-nav-link" target="_blank">Bun</ZenLink></li>
|
|
92
|
+
</ul>
|
|
93
|
+
</nav>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<!-- Legacy Links -->
|
|
97
|
+
<div style="margin: 20px 0; padding: 20px; border: 1px solid #ccc; border-radius: 8px;">
|
|
98
|
+
<h3>📍 Legacy Navigation (Standard Links)</h3>
|
|
99
|
+
<p>Regular <code><a></code> tags still work (full page reload):</p>
|
|
100
|
+
<nav>
|
|
101
|
+
<ul style="list-style: none; padding: 0; display: flex; gap: 12px; flex-wrap: wrap;">
|
|
102
|
+
<li><a href="/" class="legacy-link">Home</a></li>
|
|
103
|
+
<li><a href="/about" class="legacy-link">About</a></li>
|
|
104
|
+
<li><a href="/blog" class="legacy-link">Blog</a></li>
|
|
105
|
+
</ul>
|
|
106
|
+
</nav>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<div style="margin: 20px 0; padding: 20px; border: 1px solid #ccc; border-radius: 8px;">
|
|
110
|
+
<h3>🧩 Component Test</h3>
|
|
111
|
+
<p>Components still work within routed pages:</p>
|
|
112
|
+
|
|
113
|
+
<div style="margin: 15px 0;">
|
|
114
|
+
<h4>Button with Parent Callback</h4>
|
|
115
|
+
<Button onClick="parentCallback" />
|
|
116
|
+
<p style="font-size: 12px; color: #666;">Check console for "Parent received clicks" messages</p>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<div style="margin: 15px 0;">
|
|
120
|
+
<h4>Link Component (legacy)</h4>
|
|
121
|
+
<Link href="/about" label="About Page" />
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<div style="margin: 20px 0; padding: 20px; border: 1px solid #ddd; border-radius: 8px; background: #f8f8f8;">
|
|
126
|
+
<h3>📁 Route Structure</h3>
|
|
127
|
+
<pre style="background: #2d2d2d; color: #f8f8f2; padding: 16px; border-radius: 4px; overflow-x: auto;">
|
|
128
|
+
pages/
|
|
129
|
+
├── index.zen → /
|
|
130
|
+
├── about.zen → /about
|
|
131
|
+
├── primitives-demo.zen → /primitives-demo
|
|
132
|
+
├── blog/
|
|
133
|
+
│ ├── index.zen → /blog
|
|
134
|
+
│ └── [id].zen → /blog/:id
|
|
135
|
+
└── posts/
|
|
136
|
+
└── [...slug].zen → /posts/*slug
|
|
137
|
+
</pre>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div style="margin: 20px 0; padding: 20px; border: 1px solid #ddd; border-radius: 8px; background: #fffbeb;">
|
|
141
|
+
<h3>📖 ZenLink API</h3>
|
|
142
|
+
<p>See <code>router/navigation/ZenLink.zen</code> for component source.</p>
|
|
143
|
+
<ul style="font-size: 14px; line-height: 1.8;">
|
|
144
|
+
<li><strong>Basic:</strong> <code><ZenLink href="/about">About</ZenLink></code></li>
|
|
145
|
+
<li><strong>With class:</strong> <code><ZenLink href="/blog" class="nav-link">Blog</ZenLink></code></li>
|
|
146
|
+
<li><strong>With click:</strong> <code><ZenLink href="/contact" onClick="handleClick">Contact</ZenLink></code></li>
|
|
147
|
+
<li><strong>Preload:</strong> <code><ZenLink href="/pricing" preload>Pricing</ZenLink></code></li>
|
|
148
|
+
<li><strong>Exact match:</strong> <code><ZenLink href="/" exact>Home</ZenLink></code></li>
|
|
149
|
+
<li><strong>Programmatic:</strong> <code>navigate('/dashboard')</code> from zenith/core</li>
|
|
150
|
+
</ul>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</Main>
|
|
154
|
+
|