lego-dom 1.3.4 → 1.5.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/CHANGELOG.md +72 -1
- package/main.js +48 -17
- package/main.min.js +2 -2
- package/package.json +1 -1
- package/parse-lego.js +2 -2
- package/vite-plugin.js +0 -14
- package/.github/workflows/deploy-docs.yml +0 -56
- package/.legodom +0 -87
- package/docs/.vitepress/config.js +0 -161
- package/docs/api/config.md +0 -95
- package/docs/api/define.md +0 -58
- package/docs/api/directives.md +0 -50
- package/docs/api/globals.md +0 -29
- package/docs/api/index.md +0 -30
- package/docs/api/lifecycle.md +0 -40
- package/docs/api/route.md +0 -37
- package/docs/api/vite-plugin.md +0 -58
- package/docs/contributing/01-welcome.md +0 -38
- package/docs/contributing/02-registry.md +0 -133
- package/docs/contributing/03-batcher.md +0 -110
- package/docs/contributing/04-reactivity.md +0 -87
- package/docs/contributing/05-caching.md +0 -59
- package/docs/contributing/06-init.md +0 -136
- package/docs/contributing/07-observer.md +0 -72
- package/docs/contributing/08-snap.md +0 -140
- package/docs/contributing/09-diffing.md +0 -69
- package/docs/contributing/10-studs.md +0 -78
- package/docs/contributing/11-scanner.md +0 -117
- package/docs/contributing/12-render.md +0 -138
- package/docs/contributing/13-directives.md +0 -243
- package/docs/contributing/14-events.md +0 -57
- package/docs/contributing/15-router.md +0 -57
- package/docs/contributing/16-state.md +0 -47
- package/docs/contributing/17-legodom.md +0 -48
- package/docs/contributing/index.md +0 -24
- package/docs/examples/form.md +0 -42
- package/docs/examples/index.md +0 -104
- package/docs/examples/routing.md +0 -409
- package/docs/examples/sfc-showcase.md +0 -34
- package/docs/examples/todo-app.md +0 -383
- package/docs/guide/cdn-usage.md +0 -354
- package/docs/guide/components.md +0 -418
- package/docs/guide/directives.md +0 -539
- package/docs/guide/directory-structure.md +0 -248
- package/docs/guide/faq.md +0 -210
- package/docs/guide/getting-started.md +0 -262
- package/docs/guide/index.md +0 -88
- package/docs/guide/lifecycle.md +0 -525
- package/docs/guide/quick-start.md +0 -49
- package/docs/guide/reactivity.md +0 -415
- package/docs/guide/routing.md +0 -334
- package/docs/guide/server-side.md +0 -134
- package/docs/guide/sfc.md +0 -464
- package/docs/guide/templating.md +0 -388
- package/docs/index.md +0 -160
- package/docs/public/logo.svg +0 -17
- package/docs/router/basic-routing.md +0 -103
- package/docs/router/cold-entry.md +0 -91
- package/docs/router/history.md +0 -69
- package/docs/router/index.md +0 -73
- package/docs/router/resolver.md +0 -74
- package/docs/router/surgical-swaps.md +0 -134
- package/docs/tutorial/01-project-setup.md +0 -152
- package/docs/tutorial/02-your-first-component.md +0 -226
- package/docs/tutorial/03-adding-routes.md +0 -279
- package/docs/tutorial/04-multi-page-app.md +0 -329
- package/docs/tutorial/05-state-and-globals.md +0 -285
- package/docs/tutorial/index.md +0 -40
- package/examples/vite-app/README.md +0 -71
- package/examples/vite-app/index.html +0 -42
- package/examples/vite-app/package.json +0 -18
- package/examples/vite-app/src/app.css +0 -3
- package/examples/vite-app/src/app.js +0 -29
- package/examples/vite-app/src/components/app-navbar.lego +0 -34
- package/examples/vite-app/src/components/customers/customer-details.lego +0 -24
- package/examples/vite-app/src/components/customers/customer-orders.lego +0 -21
- package/examples/vite-app/src/components/customers/order-list.lego +0 -55
- package/examples/vite-app/src/components/greeting-card.lego +0 -41
- package/examples/vite-app/src/components/sample-component.lego +0 -75
- package/examples/vite-app/src/components/shells/customers-shell.lego +0 -21
- package/examples/vite-app/src/components/side-menu.lego +0 -46
- package/examples/vite-app/src/components/todo-list.lego +0 -239
- package/examples/vite-app/src/components/widgets/user-card.lego +0 -27
- package/examples/vite-app/vite.config.js +0 -22
- package/tests/error.test.js +0 -74
- package/tests/main.test.js +0 -103
- package/tests/memory.test.js +0 -68
- package/tests/monitoring.test.js +0 -74
- package/tests/naming.test.js +0 -74
- package/tests/parse-lego.test.js +0 -65
- package/tests/security.test.js +0 -67
- package/tests/server.test.js +0 -114
- package/tests/syntax.test.js +0 -67
|
@@ -1,329 +0,0 @@
|
|
|
1
|
-
# Step 4: Building a Multi-Page App
|
|
2
|
-
|
|
3
|
-
Let's bring it all together! In this step, we'll complete the **index → login → welcome** flow that every real app needs. You'll see exactly how data flows between pages.
|
|
4
|
-
|
|
5
|
-
## The Complete App Structure
|
|
6
|
-
|
|
7
|
-
By the end of this page, you'll have:
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
src/components/
|
|
11
|
-
├── home-page.lego ← Landing page (/)
|
|
12
|
-
├── login-page.lego ← Login form (/login)
|
|
13
|
-
└── welcome-page.lego ← Dashboard (/welcome)
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Step 1: Create the Welcome Page
|
|
17
|
-
|
|
18
|
-
Create `src/components/welcome-page.lego`:
|
|
19
|
-
|
|
20
|
-
```html
|
|
21
|
-
<template>
|
|
22
|
-
<div class="dashboard">
|
|
23
|
-
<header>
|
|
24
|
-
<h1>Welcome, [[ username ]]! 🎉</h1>
|
|
25
|
-
<button @click="handleLogout()">Logout</button>
|
|
26
|
-
</header>
|
|
27
|
-
|
|
28
|
-
<main>
|
|
29
|
-
<div class="card">
|
|
30
|
-
<h2>You're In!</h2>
|
|
31
|
-
<p>You've successfully navigated through a complete authentication flow built with LegoDOM.</p>
|
|
32
|
-
<p>This page received your username from the login form using global state.</p>
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
<div class="stats">
|
|
36
|
-
<div class="stat">
|
|
37
|
-
<span class="value">[[ visitCount ]]</span>
|
|
38
|
-
<span class="label">Page Views</span>
|
|
39
|
-
</div>
|
|
40
|
-
<div class="stat">
|
|
41
|
-
<span class="value">[[ formatTime() ]]</span>
|
|
42
|
-
<span class="label">Current Time</span>
|
|
43
|
-
</div>
|
|
44
|
-
<div class="stat">
|
|
45
|
-
<span class="value">✓</span>
|
|
46
|
-
<span class="label">Logged In</span>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
<div class="actions">
|
|
51
|
-
<a href="/" b-link class="btn">← Back to Home</a>
|
|
52
|
-
</div>
|
|
53
|
-
</main>
|
|
54
|
-
</div>
|
|
55
|
-
</template>
|
|
56
|
-
|
|
57
|
-
<style>
|
|
58
|
-
self {
|
|
59
|
-
display: block;
|
|
60
|
-
min-height: 100vh;
|
|
61
|
-
background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%);
|
|
62
|
-
color: white;
|
|
63
|
-
padding: 2rem;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
header {
|
|
67
|
-
display: flex;
|
|
68
|
-
justify-content: space-between;
|
|
69
|
-
align-items: center;
|
|
70
|
-
max-width: 800px;
|
|
71
|
-
margin: 0 auto 3rem;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
header h1 {
|
|
75
|
-
font-size: 1.75rem;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
header button {
|
|
79
|
-
background: rgba(255,255,255,0.1);
|
|
80
|
-
color: white;
|
|
81
|
-
border: 1px solid rgba(255,255,255,0.2);
|
|
82
|
-
padding: 0.5rem 1rem;
|
|
83
|
-
border-radius: 6px;
|
|
84
|
-
cursor: pointer;
|
|
85
|
-
transition: background 0.2s;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
header button:hover {
|
|
89
|
-
background: rgba(255,255,255,0.2);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
main {
|
|
93
|
-
max-width: 800px;
|
|
94
|
-
margin: 0 auto;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.card {
|
|
98
|
-
background: rgba(255,255,255,0.05);
|
|
99
|
-
padding: 2rem;
|
|
100
|
-
border-radius: 16px;
|
|
101
|
-
margin-bottom: 2rem;
|
|
102
|
-
border: 1px solid rgba(255,255,255,0.1);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.card h2 {
|
|
106
|
-
color: #4ecca3;
|
|
107
|
-
margin-bottom: 1rem;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.card p {
|
|
111
|
-
opacity: 0.8;
|
|
112
|
-
line-height: 1.6;
|
|
113
|
-
margin-bottom: 0.5rem;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.stats {
|
|
117
|
-
display: grid;
|
|
118
|
-
grid-template-columns: repeat(3, 1fr);
|
|
119
|
-
gap: 1rem;
|
|
120
|
-
margin-bottom: 2rem;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.stat {
|
|
124
|
-
background: rgba(255,255,255,0.05);
|
|
125
|
-
padding: 1.5rem;
|
|
126
|
-
border-radius: 12px;
|
|
127
|
-
text-align: center;
|
|
128
|
-
border: 1px solid rgba(255,255,255,0.1);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.stat .value {
|
|
132
|
-
display: block;
|
|
133
|
-
font-size: 2rem;
|
|
134
|
-
font-weight: bold;
|
|
135
|
-
color: #4ecca3;
|
|
136
|
-
margin-bottom: 0.5rem;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.stat .label {
|
|
140
|
-
font-size: 0.85rem;
|
|
141
|
-
opacity: 0.7;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.actions {
|
|
145
|
-
text-align: center;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.btn {
|
|
149
|
-
display: inline-block;
|
|
150
|
-
padding: 0.75rem 1.5rem;
|
|
151
|
-
background: #4ecca3;
|
|
152
|
-
color: #1a1a2e;
|
|
153
|
-
text-decoration: none;
|
|
154
|
-
border-radius: 8px;
|
|
155
|
-
font-weight: 600;
|
|
156
|
-
}
|
|
157
|
-
</style>
|
|
158
|
-
|
|
159
|
-
<script>
|
|
160
|
-
export default {
|
|
161
|
-
visitCount: 0,
|
|
162
|
-
|
|
163
|
-
get username() {
|
|
164
|
-
// Get username from global state (set by login page)
|
|
165
|
-
return Lego.globals.user?.name || 'Guest';
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
mounted() {
|
|
169
|
-
this.visitCount++;
|
|
170
|
-
|
|
171
|
-
// Redirect to login if not authenticated
|
|
172
|
-
if (!Lego.globals.user) {
|
|
173
|
-
console.log('Not logged in, redirecting...');
|
|
174
|
-
this.$go('/login').get();
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
|
|
178
|
-
formatTime() {
|
|
179
|
-
return new Date().toLocaleTimeString();
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
handleLogout() {
|
|
183
|
-
// Clear global user state
|
|
184
|
-
Lego.globals.user = null;
|
|
185
|
-
this.$go('/').get();
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
</script>
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## Step 2: Update Login to Set Global State
|
|
192
|
-
|
|
193
|
-
The login page needs to store the user in global state. Update `src/components/login-page.lego`'s script section:
|
|
194
|
-
|
|
195
|
-
```javascript
|
|
196
|
-
<script>
|
|
197
|
-
export default {
|
|
198
|
-
email: '',
|
|
199
|
-
password: '',
|
|
200
|
-
|
|
201
|
-
handleSubmit(event) {
|
|
202
|
-
event.preventDefault();
|
|
203
|
-
|
|
204
|
-
// Store user in GLOBAL state (accessible from any component!)
|
|
205
|
-
Lego.globals.user = {
|
|
206
|
-
name: this.email.split('@')[0], // Use email prefix as name
|
|
207
|
-
email: this.email,
|
|
208
|
-
loggedInAt: new Date()
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
console.log('User logged in:', Lego.globals.user);
|
|
212
|
-
|
|
213
|
-
// Navigate to welcome page
|
|
214
|
-
this.$go('/welcome').get();
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
</script>
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
## Step 3: Update Home Page Navigation
|
|
221
|
-
|
|
222
|
-
Update `src/components/home-page.lego`'s `handleClick` method:
|
|
223
|
-
|
|
224
|
-
```javascript
|
|
225
|
-
handleClick() {
|
|
226
|
-
this.$go('/login').get();
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
## Step 4: Complete `app.js`
|
|
231
|
-
|
|
232
|
-
Here's the final `src/app.js`:
|
|
233
|
-
|
|
234
|
-
```javascript
|
|
235
|
-
import { Lego } from 'lego-dom';
|
|
236
|
-
import registerComponents from 'virtual:lego-components';
|
|
237
|
-
|
|
238
|
-
// Register all .lego components
|
|
239
|
-
registerComponents();
|
|
240
|
-
|
|
241
|
-
// Define routes
|
|
242
|
-
Lego.route('/', 'home-page');
|
|
243
|
-
Lego.route('/login', 'login-page');
|
|
244
|
-
Lego.route('/welcome', 'welcome-page');
|
|
245
|
-
|
|
246
|
-
// Initialize with default user state
|
|
247
|
-
Lego.globals.user = null;
|
|
248
|
-
|
|
249
|
-
// Start the engine
|
|
250
|
-
await Lego.init();
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
## Test the Complete Flow
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
npm run dev
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
1. **Home Page** (`/`) – Click "Get Started"
|
|
260
|
-
2. **Login Page** (`/login`) – Enter an email, click "Sign In"
|
|
261
|
-
3. **Welcome Page** (`/welcome`) – See your username displayed!
|
|
262
|
-
4. Click "Logout" – Clears state, returns to home
|
|
263
|
-
5. Try navigating directly to `/welcome` – Redirects to login!
|
|
264
|
-
|
|
265
|
-
## The Data Flow
|
|
266
|
-
|
|
267
|
-
```
|
|
268
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
269
|
-
│ Lego.globals │
|
|
270
|
-
│ ┌─────────────────────────────────────────────────────┐ │
|
|
271
|
-
│ │ user: { name: 'john', email: 'john@test.com' } │ │
|
|
272
|
-
│ └─────────────────────────────────────────────────────┘ │
|
|
273
|
-
└─────────────────────────────────────────────────────────────┘
|
|
274
|
-
▲ │
|
|
275
|
-
│ writes │ reads
|
|
276
|
-
│ ▼
|
|
277
|
-
┌──────────┐ ┌──────────────┐
|
|
278
|
-
│ login │ │ welcome │
|
|
279
|
-
│ page │ │ page │
|
|
280
|
-
└──────────┘ └──────────────┘
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
## Auth Guard Pattern
|
|
284
|
-
|
|
285
|
-
Want to protect routes? Add middleware:
|
|
286
|
-
|
|
287
|
-
```javascript
|
|
288
|
-
// In app.js
|
|
289
|
-
|
|
290
|
-
const requireAuth = (params, globals) => {
|
|
291
|
-
if (!globals.user) {
|
|
292
|
-
globals.$go('/login').get();
|
|
293
|
-
return false; // Block navigation
|
|
294
|
-
}
|
|
295
|
-
return true; // Allow navigation
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
Lego.route('/welcome', 'welcome-page', requireAuth);
|
|
299
|
-
Lego.route('/dashboard', 'dashboard-page', requireAuth);
|
|
300
|
-
Lego.route('/settings', 'settings-page', requireAuth);
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
## What You've Built
|
|
304
|
-
|
|
305
|
-
✅ A complete login flow: home → login → welcome
|
|
306
|
-
✅ Global state shared across components
|
|
307
|
-
✅ Logout functionality that clears state
|
|
308
|
-
✅ Automatic redirect when not authenticated
|
|
309
|
-
✅ Route protection with middleware
|
|
310
|
-
|
|
311
|
-
## The Full Picture
|
|
312
|
-
|
|
313
|
-
| File | Purpose |
|
|
314
|
-
|------|---------|
|
|
315
|
-
| `index.html` | Entry HTML with `<lego-router>` |
|
|
316
|
-
| `src/app.js` | Routes, globals, initialization |
|
|
317
|
-
| `src/components/*.lego` | Your page components |
|
|
318
|
-
| `vite.config.js` | Vite + LegoDOM plugin setup |
|
|
319
|
-
|
|
320
|
-
---
|
|
321
|
-
|
|
322
|
-
<div style="display: flex; justify-content: space-between; margin-top: 3rem;">
|
|
323
|
-
<a href="./03-adding-routes" style="display: inline-block; background: #eee; color: #333; padding: 0.75rem 1.5rem; border-radius: 6px; text-decoration: none; font-weight: 600;">
|
|
324
|
-
← Previous: Adding Routes
|
|
325
|
-
</a>
|
|
326
|
-
<a href="./05-state-and-globals" style="display: inline-block; background: #4CAF50; color: white; padding: 0.75rem 1.5rem; border-radius: 6px; text-decoration: none; font-weight: 600;">
|
|
327
|
-
Next: State & Globals →
|
|
328
|
-
</a>
|
|
329
|
-
</div>
|
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
# Step 5: State & Globals
|
|
2
|
-
|
|
3
|
-
You've built a complete app! Now let's understand how state management works in LegoDOM and explore advanced patterns.
|
|
4
|
-
|
|
5
|
-
## Two Levels of State
|
|
6
|
-
|
|
7
|
-
### 1. Component State (Local)
|
|
8
|
-
|
|
9
|
-
Each component has its own reactive state defined in the `<script>` section:
|
|
10
|
-
|
|
11
|
-
```javascript
|
|
12
|
-
export default {
|
|
13
|
-
// This is local to THIS component instance
|
|
14
|
-
count: 0,
|
|
15
|
-
items: [],
|
|
16
|
-
|
|
17
|
-
increment() {
|
|
18
|
-
this.count++; // Triggers re-render of THIS component only
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### 2. Global State (`Lego.globals`)
|
|
24
|
-
|
|
25
|
-
Shared across ALL components. Perfect for user sessions, themes, shopping carts, etc.
|
|
26
|
-
|
|
27
|
-
```javascript
|
|
28
|
-
// In app.js or any component
|
|
29
|
-
Lego.globals.user = { name: 'John' };
|
|
30
|
-
Lego.globals.theme = 'dark';
|
|
31
|
-
Lego.globals.cart = [];
|
|
32
|
-
|
|
33
|
-
// In any component
|
|
34
|
-
console.log(Lego.globals.user.name); // 'John'
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Accessing Globals in Components
|
|
38
|
-
|
|
39
|
-
### In JavaScript (Methods)
|
|
40
|
-
|
|
41
|
-
```javascript
|
|
42
|
-
export default {
|
|
43
|
-
mounted() {
|
|
44
|
-
// Direct access
|
|
45
|
-
console.log(Lego.globals.user);
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
toggleTheme() {
|
|
49
|
-
Lego.globals.theme = Lego.globals.theme === 'dark' ? 'light' : 'dark';
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### In Templates
|
|
55
|
-
|
|
56
|
-
Use the `global` keyword:
|
|
57
|
-
|
|
58
|
-
```html
|
|
59
|
-
<template>
|
|
60
|
-
<p>Hello, [[ global.user.name ]]!</p>
|
|
61
|
-
<div class="[[ global.theme ]]">
|
|
62
|
-
Content styled by theme
|
|
63
|
-
</div>
|
|
64
|
-
<button b-show="global.user">Logout</button>
|
|
65
|
-
</template>
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Route State (`$route`)
|
|
69
|
-
|
|
70
|
-
Access current route information:
|
|
71
|
-
|
|
72
|
-
```javascript
|
|
73
|
-
// Available in any component
|
|
74
|
-
this.$route.url // '/users/42?tab=posts'
|
|
75
|
-
this.$route.route // '/users/:id'
|
|
76
|
-
this.$route.params // { id: '42' }
|
|
77
|
-
this.$route.query // { tab: 'posts' }
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
```html
|
|
81
|
-
<template>
|
|
82
|
-
<h1>User [[ $route.params.id ]]</h1>
|
|
83
|
-
<p>Current tab: [[ $route.query.tab ]]</p>
|
|
84
|
-
</template>
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## State Patterns
|
|
88
|
-
|
|
89
|
-
### Pattern 1: User Authentication
|
|
90
|
-
|
|
91
|
-
```javascript
|
|
92
|
-
// app.js
|
|
93
|
-
Lego.globals.user = null; // Initialize
|
|
94
|
-
|
|
95
|
-
// login-page.lego
|
|
96
|
-
handleLogin() {
|
|
97
|
-
Lego.globals.user = { name: 'John', token: 'abc123' };
|
|
98
|
-
this.$go('/dashboard').get();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Any protected component
|
|
102
|
-
mounted() {
|
|
103
|
-
if (!Lego.globals.user) {
|
|
104
|
-
this.$go('/login').get();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Pattern 2: Theme Switching
|
|
110
|
-
|
|
111
|
-
```javascript
|
|
112
|
-
// app.js
|
|
113
|
-
Lego.globals.theme = localStorage.getItem('theme') || 'light';
|
|
114
|
-
|
|
115
|
-
// theme-toggle.lego
|
|
116
|
-
<template>
|
|
117
|
-
<button @click="toggle()">
|
|
118
|
-
[[ global.theme === 'dark' ? '☀️' : '🌙' ]]
|
|
119
|
-
</button>
|
|
120
|
-
</template>
|
|
121
|
-
|
|
122
|
-
<script>
|
|
123
|
-
export default {
|
|
124
|
-
toggle() {
|
|
125
|
-
const newTheme = Lego.globals.theme === 'dark' ? 'light' : 'dark';
|
|
126
|
-
Lego.globals.theme = newTheme;
|
|
127
|
-
localStorage.setItem('theme', newTheme);
|
|
128
|
-
document.body.className = newTheme;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
</script>
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### Pattern 3: Shopping Cart
|
|
135
|
-
|
|
136
|
-
```javascript
|
|
137
|
-
// app.js
|
|
138
|
-
Lego.globals.cart = [];
|
|
139
|
-
|
|
140
|
-
// product-card.lego
|
|
141
|
-
addToCart() {
|
|
142
|
-
Lego.globals.cart.push({
|
|
143
|
-
id: this.product.id,
|
|
144
|
-
name: this.product.name,
|
|
145
|
-
price: this.product.price
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// cart-icon.lego
|
|
150
|
-
<template>
|
|
151
|
-
<span class="cart">
|
|
152
|
-
🛒 [[ global.cart.length ]]
|
|
153
|
-
</span>
|
|
154
|
-
</template>
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### Pattern 4: Fetching Data
|
|
158
|
-
|
|
159
|
-
```javascript
|
|
160
|
-
export default {
|
|
161
|
-
users: [],
|
|
162
|
-
loading: true,
|
|
163
|
-
error: null,
|
|
164
|
-
|
|
165
|
-
async mounted() {
|
|
166
|
-
try {
|
|
167
|
-
const response = await fetch('/api/users');
|
|
168
|
-
this.users = await response.json();
|
|
169
|
-
} catch (e) {
|
|
170
|
-
this.error = e.message;
|
|
171
|
-
} finally {
|
|
172
|
-
this.loading = false;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
```html
|
|
179
|
-
<template>
|
|
180
|
-
<div b-show="loading">Loading...</div>
|
|
181
|
-
<div b-show="error" class="error">[[ error ]]</div>
|
|
182
|
-
<ul b-show="!loading && !error">
|
|
183
|
-
<li b-for="user in users">[[ user.name ]]</li>
|
|
184
|
-
</ul>
|
|
185
|
-
</template>
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
## Cross-Component Communication
|
|
189
|
-
|
|
190
|
-
### Using `$emit` (Child to Parent)
|
|
191
|
-
|
|
192
|
-
```html
|
|
193
|
-
<!-- child-component.lego -->
|
|
194
|
-
<template>
|
|
195
|
-
<button @click="notifyParent()">Click Me</button>
|
|
196
|
-
</template>
|
|
197
|
-
|
|
198
|
-
<script>
|
|
199
|
-
export default {
|
|
200
|
-
notifyParent() {
|
|
201
|
-
this.$emit('custom-event', { message: 'Hello from child!' });
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
</script>
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
```html
|
|
208
|
-
<!-- parent-component.lego -->
|
|
209
|
-
<template>
|
|
210
|
-
<child-component @custom-event="handleEvent(event)"></child-component>
|
|
211
|
-
</template>
|
|
212
|
-
|
|
213
|
-
<script>
|
|
214
|
-
export default {
|
|
215
|
-
handleEvent(event) {
|
|
216
|
-
console.log(event.detail.message); // 'Hello from child!'
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
</script>
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### Using `$ancestors` (Access Parent State)
|
|
223
|
-
|
|
224
|
-
```javascript
|
|
225
|
-
// In a deeply nested component
|
|
226
|
-
mounted() {
|
|
227
|
-
// Get state from a specific ancestor by tag name
|
|
228
|
-
const parentState = this.$ancestors('user-profile');
|
|
229
|
-
console.log(parentState.userId);
|
|
230
|
-
}
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
## Best Practices
|
|
234
|
-
|
|
235
|
-
| Do | Don't |
|
|
236
|
-
|----|-------|
|
|
237
|
-
| ✅ Use `Lego.globals` for truly global state (user, theme) | ❌ Put everything in globals |
|
|
238
|
-
| ✅ Keep component state local when possible | ❌ Over-engineer state management |
|
|
239
|
-
| ✅ Initialize globals in `app.js` | ❌ Initialize globals in random components |
|
|
240
|
-
| ✅ Use `$emit` for child→parent communication | ❌ Reach into child component internals |
|
|
241
|
-
|
|
242
|
-
## Complete State Cheatsheet
|
|
243
|
-
|
|
244
|
-
| I want to... | Use this |
|
|
245
|
-
|--------------|----------|
|
|
246
|
-
| Store component-local data | `export default { myData: ... }` |
|
|
247
|
-
| Share data app-wide | `Lego.globals.myData = ...` |
|
|
248
|
-
| Read global in template | `[[ global.myData ]]` |
|
|
249
|
-
| Read global in JS | `Lego.globals.myData` |
|
|
250
|
-
| Get route params | `this.$route.params.id` |
|
|
251
|
-
| Get query string | `this.$route.query.tab` |
|
|
252
|
-
| Notify parent component | `this.$emit('event-name', data)` |
|
|
253
|
-
| Navigate with state | Set globals before `$go()` |
|
|
254
|
-
|
|
255
|
-
## What's Next?
|
|
256
|
-
|
|
257
|
-
🎉 **Congratulations!** You've completed the LegoDOM tutorial!
|
|
258
|
-
|
|
259
|
-
You now know how to:
|
|
260
|
-
- Set up a project from scratch
|
|
261
|
-
- Create beautiful components
|
|
262
|
-
- Navigate between pages
|
|
263
|
-
- Share state across your app
|
|
264
|
-
|
|
265
|
-
### Continue Learning
|
|
266
|
-
|
|
267
|
-
- [Components Deep Dive](/guide/components) – Advanced component patterns
|
|
268
|
-
- [Directives Reference](/guide/directives) – All `b-*` directives explained
|
|
269
|
-
- [Routing Guide](/guide/routing) – Surgical swaps and advanced routing
|
|
270
|
-
- [API Reference](/api/) – Complete API documentation
|
|
271
|
-
|
|
272
|
-
### Get Help
|
|
273
|
-
|
|
274
|
-
- 💬 [GitHub Discussions](https://github.com/rayattack/LegoDOM/discussions)
|
|
275
|
-
- 🐛 [Report Issues](https://github.com/rayattack/LegoDOM/issues)
|
|
276
|
-
|
|
277
|
-
---
|
|
278
|
-
|
|
279
|
-
<div style="text-align: center; margin-top: 3rem; padding: 2rem; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 16px; color: white;">
|
|
280
|
-
<h2 style="margin-bottom: 1rem;">You Did It! 🚀</h2>
|
|
281
|
-
<p style="opacity: 0.9; margin-bottom: 1.5rem;">You've built a complete multi-page app with LegoDOM.</p>
|
|
282
|
-
<a href="/guide/" style="display: inline-block; background: white; color: #667eea; padding: 0.75rem 1.5rem; border-radius: 8px; text-decoration: none; font-weight: 600;">
|
|
283
|
-
Explore More Guides →
|
|
284
|
-
</a>
|
|
285
|
-
</div>
|
package/docs/tutorial/index.md
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# Your First LegoDOM App
|
|
2
|
-
|
|
3
|
-
Welcome! In the next 15 minutes, you'll build a complete multi-page application with beautiful components, smooth navigation, and a login flow. No prior framework experience needed.
|
|
4
|
-
|
|
5
|
-
## What You'll Build
|
|
6
|
-
|
|
7
|
-
A polished app with:
|
|
8
|
-
- 🏠 **Landing Page** – Your app's front door
|
|
9
|
-
- 🔐 **Login Page** – A form that validates and navigates
|
|
10
|
-
- 🎉 **Welcome Page** – Personalized dashboard after login
|
|
11
|
-
|
|
12
|
-
All using Single File Components (`.lego` files) and client-side routing.
|
|
13
|
-
|
|
14
|
-
## Prerequisites
|
|
15
|
-
|
|
16
|
-
- Node.js 18+ installed
|
|
17
|
-
- A code editor (VS Code recommended)
|
|
18
|
-
- Basic HTML/CSS/JavaScript knowledge
|
|
19
|
-
|
|
20
|
-
## Tutorial Path
|
|
21
|
-
|
|
22
|
-
| Step | You'll Learn |
|
|
23
|
-
|------|--------------|
|
|
24
|
-
| [1. Project Setup](./01-project-setup) | Create a new project with Vite |
|
|
25
|
-
| [2. Your First Component](./02-your-first-component) | Build a `.lego` file |
|
|
26
|
-
| [3. Adding Routes](./03-adding-routes) | Navigate between pages |
|
|
27
|
-
| [4. Multi-Page App](./04-multi-page-app) | Complete login flow |
|
|
28
|
-
| [5. State & Globals](./05-state-and-globals) | Share data across pages |
|
|
29
|
-
|
|
30
|
-
## Ready?
|
|
31
|
-
|
|
32
|
-
<div style="text-align: center; margin: 2rem 0;">
|
|
33
|
-
<a href="./01-project-setup" style="display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 1rem 2rem; border-radius: 8px; text-decoration: none; font-weight: 600; font-size: 1.2rem;">
|
|
34
|
-
Start Building →
|
|
35
|
-
</a>
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
::: tip No Build Tools? No Problem!
|
|
39
|
-
If you want to skip the Vite setup and use LegoDOM via CDN, check out the [CDN Quick Start](/guide/cdn-usage). You can always come back to this tutorial later.
|
|
40
|
-
:::
|