lego-dom 1.3.3 → 1.4.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 +61 -0
- package/main.js +24 -3
- package/main.min.js +7 -0
- package/package.json +3 -1
- package/vite-plugin.js +0 -14
- package/.github/workflows/deploy-docs.yml +0 -56
- package/.legodom +0 -87
- package/docs/.vitepress/config.js +0 -162
- 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 -328
- package/docs/guide/components.md +0 -412
- 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 -420
- 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,383 +0,0 @@
|
|
|
1
|
-
# Todo App Example
|
|
2
|
-
|
|
3
|
-
A complete todo application demonstrating Lego features.
|
|
4
|
-
|
|
5
|
-
## Live Demo
|
|
6
|
-
|
|
7
|
-
<iframe src="/demos/todo-app.html" style="width:100%;height:500px;border:1px solid #ddd;border-radius:4px;"></iframe>
|
|
8
|
-
|
|
9
|
-
## Full Source Code
|
|
10
|
-
|
|
11
|
-
```html
|
|
12
|
-
<!DOCTYPE html>
|
|
13
|
-
<html lang="en">
|
|
14
|
-
<head>
|
|
15
|
-
<meta charset="UTF-8">
|
|
16
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
17
|
-
<title>Todo App - Lego</title>
|
|
18
|
-
<style>
|
|
19
|
-
body {
|
|
20
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
21
|
-
max-width: 600px;
|
|
22
|
-
margin: 2rem auto;
|
|
23
|
-
padding: 0 1rem;
|
|
24
|
-
background: #f5f5f5;
|
|
25
|
-
}
|
|
26
|
-
h1 {
|
|
27
|
-
text-align: center;
|
|
28
|
-
color: #333;
|
|
29
|
-
}
|
|
30
|
-
</style>
|
|
31
|
-
</head>
|
|
32
|
-
<body>
|
|
33
|
-
<h1>📝 Todo App</h1>
|
|
34
|
-
|
|
35
|
-
<todo-app></todo-app>
|
|
36
|
-
|
|
37
|
-
<script src="https://unpkg.com/lego-dom/main.js"></script>
|
|
38
|
-
|
|
39
|
-
<template b-id="todo-app">
|
|
40
|
-
<style>
|
|
41
|
-
self {
|
|
42
|
-
display: block;
|
|
43
|
-
background: white;
|
|
44
|
-
border-radius: 8px;
|
|
45
|
-
padding: 1.5rem;
|
|
46
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.input-group {
|
|
50
|
-
display: flex;
|
|
51
|
-
gap: 0.5rem;
|
|
52
|
-
margin-bottom: 1.5rem;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
input[type="text"] {
|
|
56
|
-
flex: 1;
|
|
57
|
-
padding: 0.75rem;
|
|
58
|
-
font-size: 1rem;
|
|
59
|
-
border: 2px solid #e0e0e0;
|
|
60
|
-
border-radius: 4px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
input[type="text"]:focus {
|
|
64
|
-
outline: none;
|
|
65
|
-
border-color: #4CAF50;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.btn {
|
|
69
|
-
padding: 0.75rem 1.5rem;
|
|
70
|
-
font-size: 1rem;
|
|
71
|
-
border: none;
|
|
72
|
-
border-radius: 4px;
|
|
73
|
-
cursor: pointer;
|
|
74
|
-
font-weight: 600;
|
|
75
|
-
transition: background 0.2s;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.btn-primary {
|
|
79
|
-
background: #4CAF50;
|
|
80
|
-
color: white;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.btn-primary:hover {
|
|
84
|
-
background: #45a049;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
.filters {
|
|
88
|
-
display: flex;
|
|
89
|
-
gap: 0.5rem;
|
|
90
|
-
margin-bottom: 1rem;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.filter-btn {
|
|
94
|
-
padding: 0.5rem 1rem;
|
|
95
|
-
background: #f0f0f0;
|
|
96
|
-
border: none;
|
|
97
|
-
border-radius: 4px;
|
|
98
|
-
cursor: pointer;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
.filter-btn.active {
|
|
102
|
-
background: #4CAF50;
|
|
103
|
-
color: white;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
ul {
|
|
107
|
-
list-style: none;
|
|
108
|
-
padding: 0;
|
|
109
|
-
margin: 0;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
li {
|
|
113
|
-
display: flex;
|
|
114
|
-
align-items: center;
|
|
115
|
-
gap: 0.75rem;
|
|
116
|
-
padding: 0.75rem;
|
|
117
|
-
border-bottom: 1px solid #f0f0f0;
|
|
118
|
-
transition: background 0.2s;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
li:hover {
|
|
122
|
-
background: #f9f9f9;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
input[type="checkbox"] {
|
|
126
|
-
width: 20px;
|
|
127
|
-
height: 20px;
|
|
128
|
-
cursor: pointer;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.todo-text {
|
|
132
|
-
flex: 1;
|
|
133
|
-
font-size: 1rem;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.todo-text.done {
|
|
137
|
-
text-decoration: line-through;
|
|
138
|
-
color: #999;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.delete-btn {
|
|
142
|
-
padding: 0.25rem 0.5rem;
|
|
143
|
-
background: #f44336;
|
|
144
|
-
color: white;
|
|
145
|
-
border: none;
|
|
146
|
-
border-radius: 4px;
|
|
147
|
-
cursor: pointer;
|
|
148
|
-
font-size: 0.875rem;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.delete-btn:hover {
|
|
152
|
-
background: #da190b;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
.stats {
|
|
156
|
-
margin-top: 1rem;
|
|
157
|
-
padding-top: 1rem;
|
|
158
|
-
border-top: 2px solid #f0f0f0;
|
|
159
|
-
display: flex;
|
|
160
|
-
justify-content: space-between;
|
|
161
|
-
color: #666;
|
|
162
|
-
font-size: 0.875rem;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
.clear-completed {
|
|
166
|
-
background: none;
|
|
167
|
-
border: none;
|
|
168
|
-
color: #f44336;
|
|
169
|
-
cursor: pointer;
|
|
170
|
-
text-decoration: underline;
|
|
171
|
-
}
|
|
172
|
-
</style>
|
|
173
|
-
|
|
174
|
-
<div class="input-group">
|
|
175
|
-
<input
|
|
176
|
-
type="text"
|
|
177
|
-
b-sync="newTodo"
|
|
178
|
-
placeholder="What needs to be done?"
|
|
179
|
-
@keyup="event.key === 'Enter' && addTodo()">
|
|
180
|
-
<button class="btn btn-primary" @click="addTodo()">Add</button>
|
|
181
|
-
</div>
|
|
182
|
-
|
|
183
|
-
<div class="filters">
|
|
184
|
-
<button
|
|
185
|
-
class="filter-btn [[ filter === 'all' ? 'active' : '' ]]"
|
|
186
|
-
@click="filter = 'all'">
|
|
187
|
-
All
|
|
188
|
-
</button>
|
|
189
|
-
<button
|
|
190
|
-
class="filter-btn [[ filter === 'active' ? 'active' : '' ]]"
|
|
191
|
-
@click="filter = 'active'">
|
|
192
|
-
Active
|
|
193
|
-
</button>
|
|
194
|
-
<button
|
|
195
|
-
class="filter-btn [[ filter === 'completed' ? 'active' : '' ]]"
|
|
196
|
-
@click="filter = 'completed'">
|
|
197
|
-
Completed
|
|
198
|
-
</button>
|
|
199
|
-
</div>
|
|
200
|
-
|
|
201
|
-
<ul>
|
|
202
|
-
<li b-for="todo in filteredTodos()">
|
|
203
|
-
<input type="checkbox" b-sync="todo.done">
|
|
204
|
-
<span class="todo-text [[ todo.done ? 'done' : '' ]]">
|
|
205
|
-
[[ todo.text ]]
|
|
206
|
-
</span>
|
|
207
|
-
<button class="delete-btn" @click="deleteTodo(todo)">Delete</button>
|
|
208
|
-
</li>
|
|
209
|
-
</ul>
|
|
210
|
-
|
|
211
|
-
<div class="stats">
|
|
212
|
-
<span>[[ remaining() ]] item[[ remaining() === 1 ? '' : 's' ]] left</span>
|
|
213
|
-
<button
|
|
214
|
-
class="clear-completed"
|
|
215
|
-
b-show="completedCount() > 0"
|
|
216
|
-
@click="clearCompleted()">
|
|
217
|
-
Clear completed ([[ completedCount() ]])
|
|
218
|
-
</button>
|
|
219
|
-
</div>
|
|
220
|
-
</template>
|
|
221
|
-
|
|
222
|
-
<script>
|
|
223
|
-
Lego.define('todo-app',
|
|
224
|
-
document.querySelector('template[b-id="todo-app"]').innerHTML,
|
|
225
|
-
{
|
|
226
|
-
newTodo: '',
|
|
227
|
-
filter: 'all',
|
|
228
|
-
todos: [],
|
|
229
|
-
|
|
230
|
-
mounted() {
|
|
231
|
-
// Load from localStorage
|
|
232
|
-
const saved = localStorage.getItem('legojs-todos');
|
|
233
|
-
if (saved) {
|
|
234
|
-
this.todos = JSON.parse(saved);
|
|
235
|
-
}
|
|
236
|
-
},
|
|
237
|
-
|
|
238
|
-
updated() {
|
|
239
|
-
// Save to localStorage
|
|
240
|
-
localStorage.setItem('legojs-todos', JSON.stringify(this.todos));
|
|
241
|
-
},
|
|
242
|
-
|
|
243
|
-
addTodo() {
|
|
244
|
-
if (this.newTodo.trim()) {
|
|
245
|
-
this.todos.push({
|
|
246
|
-
id: Date.now(),
|
|
247
|
-
text: this.newTodo,
|
|
248
|
-
done: false
|
|
249
|
-
});
|
|
250
|
-
this.newTodo = '';
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
|
|
254
|
-
deleteTodo(todo) {
|
|
255
|
-
const index = this.todos.indexOf(todo);
|
|
256
|
-
if (index > -1) {
|
|
257
|
-
this.todos.splice(index, 1);
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
filteredTodos() {
|
|
262
|
-
if (this.filter === 'active') {
|
|
263
|
-
return this.todos.filter(t => !t.done);
|
|
264
|
-
} else if (this.filter === 'completed') {
|
|
265
|
-
return this.todos.filter(t => t.done);
|
|
266
|
-
}
|
|
267
|
-
return this.todos;
|
|
268
|
-
},
|
|
269
|
-
|
|
270
|
-
remaining() {
|
|
271
|
-
return this.todos.filter(t => !t.done).length;
|
|
272
|
-
},
|
|
273
|
-
|
|
274
|
-
completedCount() {
|
|
275
|
-
return this.todos.filter(t => t.done).length;
|
|
276
|
-
},
|
|
277
|
-
|
|
278
|
-
clearCompleted() {
|
|
279
|
-
this.todos = this.todos.filter(t => !t.done);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
);
|
|
283
|
-
</script>
|
|
284
|
-
</body>
|
|
285
|
-
</html>
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
## Features Demonstrated
|
|
289
|
-
|
|
290
|
-
### ✅ Reactivity
|
|
291
|
-
- Auto-updates when todos change
|
|
292
|
-
- Two-way binding with `b-sync`
|
|
293
|
-
- Computed values (`remaining()`, `completedCount()`)
|
|
294
|
-
|
|
295
|
-
### ✅ List Rendering
|
|
296
|
-
- `b-for` to iterate over todos
|
|
297
|
-
- Dynamic filtering based on status
|
|
298
|
-
|
|
299
|
-
### ✅ Event Handling
|
|
300
|
-
- Add on Enter key
|
|
301
|
-
- Click to complete/delete
|
|
302
|
-
- Filter buttons
|
|
303
|
-
|
|
304
|
-
### ✅ Lifecycle Hooks
|
|
305
|
-
- `mounted()` - Load from localStorage
|
|
306
|
-
- `updated()` - Save to localStorage
|
|
307
|
-
|
|
308
|
-
### ✅ Conditional Rendering
|
|
309
|
-
- Show/hide "Clear completed" button
|
|
310
|
-
- Different styles for completed items
|
|
311
|
-
|
|
312
|
-
### ✅ Methods
|
|
313
|
-
- `addTodo()` - Add new item
|
|
314
|
-
- `deleteTodo()` - Remove item
|
|
315
|
-
- `filteredTodos()` - Filter logic
|
|
316
|
-
- `clearCompleted()` - Batch delete
|
|
317
|
-
|
|
318
|
-
## Key Concepts
|
|
319
|
-
|
|
320
|
-
### Local Storage Persistence
|
|
321
|
-
|
|
322
|
-
```js
|
|
323
|
-
mounted() {
|
|
324
|
-
const saved = localStorage.getItem('legojs-todos');
|
|
325
|
-
if (saved) {
|
|
326
|
-
this.todos = JSON.parse(saved);
|
|
327
|
-
}
|
|
328
|
-
},
|
|
329
|
-
|
|
330
|
-
updated() {
|
|
331
|
-
localStorage.setItem('legojs-todos', JSON.stringify(this.todos));
|
|
332
|
-
}
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
### Filtering
|
|
336
|
-
|
|
337
|
-
```js
|
|
338
|
-
filteredTodos() {
|
|
339
|
-
if (this.filter === 'active') {
|
|
340
|
-
return this.todos.filter(t => !t.done);
|
|
341
|
-
} else if (this.filter === 'completed') {
|
|
342
|
-
return this.todos.filter(t => t.done);
|
|
343
|
-
}
|
|
344
|
-
return this.todos;
|
|
345
|
-
}
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
### Array Manipulation
|
|
349
|
-
|
|
350
|
-
```js
|
|
351
|
-
// Add
|
|
352
|
-
this.todos.push({ ... });
|
|
353
|
-
|
|
354
|
-
// Remove
|
|
355
|
-
this.todos.splice(index, 1);
|
|
356
|
-
|
|
357
|
-
// Filter (reassign)
|
|
358
|
-
this.todos = this.todos.filter(t => !t.done);
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
## Try It Yourself
|
|
362
|
-
|
|
363
|
-
1. Copy the code above
|
|
364
|
-
2. Save as `todo.html`
|
|
365
|
-
3. Open in a browser
|
|
366
|
-
4. Add todos, mark as complete, filter, delete
|
|
367
|
-
5. Refresh—todos persist!
|
|
368
|
-
|
|
369
|
-
## Extensions
|
|
370
|
-
|
|
371
|
-
Try adding these features:
|
|
372
|
-
|
|
373
|
-
- **Edit mode** - Double click to edit todo text
|
|
374
|
-
- **Due dates** - Add date picker and sort by date
|
|
375
|
-
- **Categories** - Organize todos into lists
|
|
376
|
-
- **Drag & drop** - Reorder todos
|
|
377
|
-
- **Export/Import** - Download/upload todo list
|
|
378
|
-
|
|
379
|
-
## Next Steps
|
|
380
|
-
|
|
381
|
-
- See [Routing Example](/examples/routing)
|
|
382
|
-
- Learn about [Form Validation](/examples/form)
|
|
383
|
-
- Explore [SFC Showcase](/examples/sfc-showcase)
|
package/docs/guide/cdn-usage.md
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
# CDN Usage
|
|
2
|
-
|
|
3
|
-
Lego works perfectly without any build tools. Just include it via CDN and start building!
|
|
4
|
-
|
|
5
|
-
## Quick Start
|
|
6
|
-
|
|
7
|
-
```html
|
|
8
|
-
<!DOCTYPE html>
|
|
9
|
-
<html>
|
|
10
|
-
<head>
|
|
11
|
-
<title>My App</title>
|
|
12
|
-
</head>
|
|
13
|
-
<body>
|
|
14
|
-
<!-- Define your component -->
|
|
15
|
-
<template b-id="hello-world">
|
|
16
|
-
<h1>[[ message ]]</h1>
|
|
17
|
-
</template>
|
|
18
|
-
|
|
19
|
-
<!-- Use it -->
|
|
20
|
-
<hello-world b-data="{ message: 'Hello from CDN!' }"></hello-world>
|
|
21
|
-
|
|
22
|
-
<!-- Include Lego -->
|
|
23
|
-
<script src="https://unpkg.com/lego-dom/main.js"></script>
|
|
24
|
-
<script>
|
|
25
|
-
Lego.init();
|
|
26
|
-
</script>
|
|
27
|
-
</body>
|
|
28
|
-
</html>
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
That's it! Open this file in any browser and it works.
|
|
32
|
-
|
|
33
|
-
## CDN Providers
|
|
34
|
-
|
|
35
|
-
### unpkg (Recommended)
|
|
36
|
-
|
|
37
|
-
```html
|
|
38
|
-
<!-- Latest version -->
|
|
39
|
-
<script src="https://unpkg.com/lego-dom/main.js"></script>
|
|
40
|
-
|
|
41
|
-
<!-- Specific version -->
|
|
42
|
-
<script src="https://unpkg.com/lego-dom@0.0.7/main.js"></script>
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### jsdelivr
|
|
46
|
-
|
|
47
|
-
```html
|
|
48
|
-
<!-- Latest version -->
|
|
49
|
-
<script src="https://cdn.jsdelivr.net/npm/lego-dom/main.js"></script>
|
|
50
|
-
|
|
51
|
-
<!-- Specific version -->
|
|
52
|
-
<script src="https://cdn.jsdelivr.net/npm/lego-dom@0.0.7/main.js"></script>
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### cdnjs
|
|
56
|
-
|
|
57
|
-
```html
|
|
58
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/lego-dom/0.0.7/main.js"></script>
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Complete Example
|
|
62
|
-
|
|
63
|
-
Here's a full working application using only CDN:
|
|
64
|
-
|
|
65
|
-
```html
|
|
66
|
-
<!DOCTYPE html>
|
|
67
|
-
<html lang="en">
|
|
68
|
-
<head>
|
|
69
|
-
<meta charset="UTF-8">
|
|
70
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
71
|
-
<title>Todo App - Lego</title>
|
|
72
|
-
<style>
|
|
73
|
-
body {
|
|
74
|
-
font-family: system-ui, sans-serif;
|
|
75
|
-
max-width: 600px;
|
|
76
|
-
margin: 2rem auto;
|
|
77
|
-
padding: 0 1rem;
|
|
78
|
-
}
|
|
79
|
-
</style>
|
|
80
|
-
</head>
|
|
81
|
-
<body>
|
|
82
|
-
<h1>My Todo App</h1>
|
|
83
|
-
<todo-app></todo-app>
|
|
84
|
-
|
|
85
|
-
<template b-id="todo-app">
|
|
86
|
-
<style>
|
|
87
|
-
self {
|
|
88
|
-
display: block;
|
|
89
|
-
}
|
|
90
|
-
.input-group {
|
|
91
|
-
display: flex;
|
|
92
|
-
gap: 0.5rem;
|
|
93
|
-
margin-bottom: 1rem;
|
|
94
|
-
}
|
|
95
|
-
input {
|
|
96
|
-
flex: 1;
|
|
97
|
-
padding: 0.5rem;
|
|
98
|
-
font-size: 1rem;
|
|
99
|
-
}
|
|
100
|
-
button {
|
|
101
|
-
padding: 0.5rem 1rem;
|
|
102
|
-
font-size: 1rem;
|
|
103
|
-
background: #4CAF50;
|
|
104
|
-
color: white;
|
|
105
|
-
border: none;
|
|
106
|
-
cursor: pointer;
|
|
107
|
-
}
|
|
108
|
-
ul {
|
|
109
|
-
list-style: none;
|
|
110
|
-
padding: 0;
|
|
111
|
-
}
|
|
112
|
-
li {
|
|
113
|
-
padding: 0.75rem;
|
|
114
|
-
border-bottom: 1px solid #eee;
|
|
115
|
-
display: flex;
|
|
116
|
-
align-items: center;
|
|
117
|
-
gap: 0.5rem;
|
|
118
|
-
}
|
|
119
|
-
.done {
|
|
120
|
-
text-decoration: line-through;
|
|
121
|
-
opacity: 0.6;
|
|
122
|
-
}
|
|
123
|
-
</style>
|
|
124
|
-
|
|
125
|
-
<div class="input-group">
|
|
126
|
-
<input
|
|
127
|
-
b-sync="newTodo"
|
|
128
|
-
placeholder="What needs to be done?"
|
|
129
|
-
@keyup="event.key === 'Enter' && addTodo()">
|
|
130
|
-
<button @click="addTodo()">Add</button>
|
|
131
|
-
</div>
|
|
132
|
-
|
|
133
|
-
<ul>
|
|
134
|
-
<li b-for="todo in todos">
|
|
135
|
-
<input type="checkbox" b-sync="todo.done">
|
|
136
|
-
<span class="[[ todo.done ? 'done' : '' ]]">
|
|
137
|
-
[[ todo.text ]]
|
|
138
|
-
</span>
|
|
139
|
-
</li>
|
|
140
|
-
</ul>
|
|
141
|
-
|
|
142
|
-
<p>[[ remaining() ]] remaining</p>
|
|
143
|
-
</template>
|
|
144
|
-
|
|
145
|
-
<script src="https://unpkg.com/lego-dom/main.js"></script>
|
|
146
|
-
|
|
147
|
-
<script>
|
|
148
|
-
// Initialize with data
|
|
149
|
-
Lego.define('todo-app', Lego.registry['todo-app'].innerHTML, {
|
|
150
|
-
newTodo: '',
|
|
151
|
-
todos: [
|
|
152
|
-
{ text: 'Learn Lego', done: true },
|
|
153
|
-
{ text: 'Build something awesome', done: false }
|
|
154
|
-
],
|
|
155
|
-
addTodo() {
|
|
156
|
-
if (this.newTodo.trim()) {
|
|
157
|
-
this.todos.push({
|
|
158
|
-
text: this.newTodo,
|
|
159
|
-
done: false
|
|
160
|
-
});
|
|
161
|
-
this.newTodo = '';
|
|
162
|
-
}
|
|
163
|
-
},
|
|
164
|
-
remaining() {
|
|
165
|
-
return this.todos.filter(t => !t.done).length;
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Don't forget to init!
|
|
170
|
-
Lego.init();
|
|
171
|
-
</script>
|
|
172
|
-
</body>
|
|
173
|
-
</html>
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## Progressive Enhancement
|
|
177
|
-
|
|
178
|
-
Lego is perfect for progressively enhancing existing sites:
|
|
179
|
-
|
|
180
|
-
```html
|
|
181
|
-
<!-- Your existing page -->
|
|
182
|
-
<div id="legacy-content">
|
|
183
|
-
<h1>My Existing Site</h1>
|
|
184
|
-
<p>This works without JavaScript</p>
|
|
185
|
-
</div>
|
|
186
|
-
|
|
187
|
-
<!-- Add interactive components -->
|
|
188
|
-
<user-widget></user-widget>
|
|
189
|
-
|
|
190
|
-
<template b-id="user-widget">
|
|
191
|
-
<style>
|
|
192
|
-
self {
|
|
193
|
-
position: fixed;
|
|
194
|
-
bottom: 1rem;
|
|
195
|
-
right: 1rem;
|
|
196
|
-
background: white;
|
|
197
|
-
padding: 1rem;
|
|
198
|
-
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
199
|
-
}
|
|
200
|
-
</style>
|
|
201
|
-
<p>Welcome, [[ username ]]!</p>
|
|
202
|
-
<button @click="logout()">Logout</button>
|
|
203
|
-
</template>
|
|
204
|
-
|
|
205
|
-
<script src="https://unpkg.com/lego-dom/main.js"></script>
|
|
206
|
-
<script>
|
|
207
|
-
Lego.define('user-widget', Lego.registry['user-widget'].innerHTML, {
|
|
208
|
-
username: 'Guest',
|
|
209
|
-
async mounted() {
|
|
210
|
-
const user = await fetch('/api/user').then(r => r.json());
|
|
211
|
-
this.username = user.name;
|
|
212
|
-
},
|
|
213
|
-
logout() {
|
|
214
|
-
window.location.href = '/logout';
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
Lego.init();
|
|
219
|
-
</script>
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
## Embedding in Existing Apps
|
|
223
|
-
|
|
224
|
-
Lego components work alongside other frameworks:
|
|
225
|
-
|
|
226
|
-
```html
|
|
227
|
-
<!-- Works fine with jQuery, Bootstrap, etc. -->
|
|
228
|
-
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
229
|
-
<script src="https://unpkg.com/lego-dom/main.js"></script>
|
|
230
|
-
|
|
231
|
-
<!-- Your Lego component -->
|
|
232
|
-
<my-component></my-component>
|
|
233
|
-
|
|
234
|
-
<!-- Your jQuery code -->
|
|
235
|
-
<script>
|
|
236
|
-
$(document).ready(function() {
|
|
237
|
-
// jQuery code here
|
|
238
|
-
});
|
|
239
|
-
</script>
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
## Loading Strategy
|
|
243
|
-
|
|
244
|
-
### For Production
|
|
245
|
-
|
|
246
|
-
Always pin to a specific version:
|
|
247
|
-
|
|
248
|
-
```html
|
|
249
|
-
<script src="https://unpkg.com/lego-dom@0.0.7/main.js"></script>
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
### For Development/Prototyping
|
|
253
|
-
|
|
254
|
-
Use latest:
|
|
255
|
-
|
|
256
|
-
```html
|
|
257
|
-
<script src="https://unpkg.com/lego-dom/main.js"></script>
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
### With defer
|
|
261
|
-
|
|
262
|
-
Load asynchronously without blocking page render:
|
|
263
|
-
|
|
264
|
-
```html
|
|
265
|
-
<script defer src="https://unpkg.com/lego-dom/main.js"></script>
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
### With integrity (SRI)
|
|
269
|
-
|
|
270
|
-
For maximum security:
|
|
271
|
-
|
|
272
|
-
```html
|
|
273
|
-
<script
|
|
274
|
-
src="https://unpkg.com/lego-dom@0.0.7/main.js"
|
|
275
|
-
integrity="sha384-..."
|
|
276
|
-
crossorigin="anonymous">
|
|
277
|
-
</script>
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
## Browser Compatibility
|
|
281
|
-
|
|
282
|
-
Lego works in all modern browsers:
|
|
283
|
-
|
|
284
|
-
- ✅ Chrome 63+
|
|
285
|
-
- ✅ Firefox 63+
|
|
286
|
-
- ✅ Safari 11.1+
|
|
287
|
-
- ✅ Edge 79+
|
|
288
|
-
|
|
289
|
-
No polyfills needed for these browsers!
|
|
290
|
-
|
|
291
|
-
## Pros and Cons
|
|
292
|
-
|
|
293
|
-
### ✅ Advantages
|
|
294
|
-
|
|
295
|
-
- **No build step** - Instant development
|
|
296
|
-
- **No npm** - No dependency management
|
|
297
|
-
- **Fast prototyping** - Perfect for demos and learning
|
|
298
|
-
- **Progressive enhancement** - Add to existing sites easily
|
|
299
|
-
- **Low barrier** - Great for beginners
|
|
300
|
-
|
|
301
|
-
### ⚠️ Limitations
|
|
302
|
-
|
|
303
|
-
- No tree-shaking (you get the whole library)
|
|
304
|
-
- No TypeScript compilation
|
|
305
|
-
- No `.lego` SFC support
|
|
306
|
-
- No hot module replacement
|
|
307
|
-
- Slower for large apps compared to bundled versions
|
|
308
|
-
|
|
309
|
-
## When to Use CDN
|
|
310
|
-
|
|
311
|
-
**Perfect for:**
|
|
312
|
-
- Prototypes and demos
|
|
313
|
-
- Small websites (1-5 components)
|
|
314
|
-
- Progressive enhancement
|
|
315
|
-
- Learning and experimentation
|
|
316
|
-
- CodePen/JSFiddle examples
|
|
317
|
-
|
|
318
|
-
**Consider bundling for:**
|
|
319
|
-
- Large applications (10+ components)
|
|
320
|
-
- Production apps requiring optimization
|
|
321
|
-
- Projects needing TypeScript
|
|
322
|
-
- Teams wanting SFC workflow
|
|
323
|
-
|
|
324
|
-
## Next Steps
|
|
325
|
-
|
|
326
|
-
- See [complete CDN examples](/examples/)
|
|
327
|
-
- Learn about [routing](/guide/routing) for multi-page apps
|
|
328
|
-
- Explore [directives](/guide/directives) for common patterns
|