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.
Files changed (93) hide show
  1. package/CHANGELOG.md +72 -1
  2. package/main.js +48 -17
  3. package/main.min.js +2 -2
  4. package/package.json +1 -1
  5. package/parse-lego.js +2 -2
  6. package/vite-plugin.js +0 -14
  7. package/.github/workflows/deploy-docs.yml +0 -56
  8. package/.legodom +0 -87
  9. package/docs/.vitepress/config.js +0 -161
  10. package/docs/api/config.md +0 -95
  11. package/docs/api/define.md +0 -58
  12. package/docs/api/directives.md +0 -50
  13. package/docs/api/globals.md +0 -29
  14. package/docs/api/index.md +0 -30
  15. package/docs/api/lifecycle.md +0 -40
  16. package/docs/api/route.md +0 -37
  17. package/docs/api/vite-plugin.md +0 -58
  18. package/docs/contributing/01-welcome.md +0 -38
  19. package/docs/contributing/02-registry.md +0 -133
  20. package/docs/contributing/03-batcher.md +0 -110
  21. package/docs/contributing/04-reactivity.md +0 -87
  22. package/docs/contributing/05-caching.md +0 -59
  23. package/docs/contributing/06-init.md +0 -136
  24. package/docs/contributing/07-observer.md +0 -72
  25. package/docs/contributing/08-snap.md +0 -140
  26. package/docs/contributing/09-diffing.md +0 -69
  27. package/docs/contributing/10-studs.md +0 -78
  28. package/docs/contributing/11-scanner.md +0 -117
  29. package/docs/contributing/12-render.md +0 -138
  30. package/docs/contributing/13-directives.md +0 -243
  31. package/docs/contributing/14-events.md +0 -57
  32. package/docs/contributing/15-router.md +0 -57
  33. package/docs/contributing/16-state.md +0 -47
  34. package/docs/contributing/17-legodom.md +0 -48
  35. package/docs/contributing/index.md +0 -24
  36. package/docs/examples/form.md +0 -42
  37. package/docs/examples/index.md +0 -104
  38. package/docs/examples/routing.md +0 -409
  39. package/docs/examples/sfc-showcase.md +0 -34
  40. package/docs/examples/todo-app.md +0 -383
  41. package/docs/guide/cdn-usage.md +0 -354
  42. package/docs/guide/components.md +0 -418
  43. package/docs/guide/directives.md +0 -539
  44. package/docs/guide/directory-structure.md +0 -248
  45. package/docs/guide/faq.md +0 -210
  46. package/docs/guide/getting-started.md +0 -262
  47. package/docs/guide/index.md +0 -88
  48. package/docs/guide/lifecycle.md +0 -525
  49. package/docs/guide/quick-start.md +0 -49
  50. package/docs/guide/reactivity.md +0 -415
  51. package/docs/guide/routing.md +0 -334
  52. package/docs/guide/server-side.md +0 -134
  53. package/docs/guide/sfc.md +0 -464
  54. package/docs/guide/templating.md +0 -388
  55. package/docs/index.md +0 -160
  56. package/docs/public/logo.svg +0 -17
  57. package/docs/router/basic-routing.md +0 -103
  58. package/docs/router/cold-entry.md +0 -91
  59. package/docs/router/history.md +0 -69
  60. package/docs/router/index.md +0 -73
  61. package/docs/router/resolver.md +0 -74
  62. package/docs/router/surgical-swaps.md +0 -134
  63. package/docs/tutorial/01-project-setup.md +0 -152
  64. package/docs/tutorial/02-your-first-component.md +0 -226
  65. package/docs/tutorial/03-adding-routes.md +0 -279
  66. package/docs/tutorial/04-multi-page-app.md +0 -329
  67. package/docs/tutorial/05-state-and-globals.md +0 -285
  68. package/docs/tutorial/index.md +0 -40
  69. package/examples/vite-app/README.md +0 -71
  70. package/examples/vite-app/index.html +0 -42
  71. package/examples/vite-app/package.json +0 -18
  72. package/examples/vite-app/src/app.css +0 -3
  73. package/examples/vite-app/src/app.js +0 -29
  74. package/examples/vite-app/src/components/app-navbar.lego +0 -34
  75. package/examples/vite-app/src/components/customers/customer-details.lego +0 -24
  76. package/examples/vite-app/src/components/customers/customer-orders.lego +0 -21
  77. package/examples/vite-app/src/components/customers/order-list.lego +0 -55
  78. package/examples/vite-app/src/components/greeting-card.lego +0 -41
  79. package/examples/vite-app/src/components/sample-component.lego +0 -75
  80. package/examples/vite-app/src/components/shells/customers-shell.lego +0 -21
  81. package/examples/vite-app/src/components/side-menu.lego +0 -46
  82. package/examples/vite-app/src/components/todo-list.lego +0 -239
  83. package/examples/vite-app/src/components/widgets/user-card.lego +0 -27
  84. package/examples/vite-app/vite.config.js +0 -22
  85. package/tests/error.test.js +0 -74
  86. package/tests/main.test.js +0 -103
  87. package/tests/memory.test.js +0 -68
  88. package/tests/monitoring.test.js +0 -74
  89. package/tests/naming.test.js +0 -74
  90. package/tests/parse-lego.test.js +0 -65
  91. package/tests/security.test.js +0 -67
  92. package/tests/server.test.js +0 -114
  93. package/tests/syntax.test.js +0 -67
@@ -1,415 +0,0 @@
1
- # Reactivity
2
-
3
- Understand how Lego makes your UI automatically update when data changes.
4
-
5
- ## The Core Concept
6
-
7
- When you change an object, the DOM updates automatically:
8
-
9
- ```js
10
- component._studs.count = 5; // DOM updates!
11
- component._studs.items.push('new item'); // DOM updates!
12
- ```
13
-
14
- No `setState()`, no `dispatch()`, no special syntax. Just mutate the data.
15
-
16
- ## How It Works
17
-
18
- Lego uses **ES6 Proxies** to track changes:
19
-
20
- ```js
21
- const reactive = (obj, el) => {
22
- return new Proxy(obj, {
23
- set(target, key, value) {
24
- const oldValue = target[key];
25
- target[key] = value;
26
-
27
- if (oldValue !== value) {
28
- // Schedule re-render
29
- render(el);
30
- }
31
-
32
- return true;
33
- }
34
- });
35
- };
36
- ```
37
-
38
- When you set a property, the proxy intercepts it and schedules a re-render.
39
-
40
- ## What's Reactive
41
-
42
- ### ✅ Direct Property Assignment
43
-
44
- ```js
45
- this.count = 10; // ✅ Reactive
46
- this.user.name = 'Alice'; // ✅ Reactive
47
- this.items[0] = 'updated'; // ✅ Reactive
48
- ```
49
-
50
- ### ✅ Array Methods
51
-
52
- ```js
53
- this.items.push('new'); // ✅ Reactive
54
- this.items.pop(); // ✅ Reactive
55
- this.items.splice(0, 1); // ✅ Reactive
56
- this.items.sort(); // ✅ Reactive
57
- ```
58
-
59
- ### ✅ Nested Objects
60
-
61
- ```js
62
- this.user.profile.age = 30; // ✅ Reactive
63
- ```
64
-
65
- Lego recursively wraps nested objects in proxies.
66
-
67
- ### ✅ Object Deletion
68
-
69
- ```js
70
- delete this.user.email; // ✅ Reactive
71
- ```
72
-
73
- ### ⚠️ Limitations
74
-
75
- #### Replacing Arrays
76
-
77
- Don't replace the entire array reference:
78
-
79
- ```js
80
- this.items = newItems; // ⚠️ Might not be reactive
81
- ```
82
-
83
- Instead, mutate in place:
84
-
85
- ```js
86
- this.items.length = 0;
87
- this.items.push(...newItems); // ✅ Better
88
- ```
89
-
90
- #### Adding New Root Properties
91
-
92
- Adding properties after initialization won't be reactive:
93
-
94
- ```js
95
- // Initial state
96
- {
97
- count: 0
98
- }
99
-
100
- // Later...
101
- this.newProp = 'value'; // ⚠️ Not reactive
102
- ```
103
-
104
- Initialize all properties upfront:
105
-
106
- ```js
107
- {
108
- count: 0,
109
- newProp: null // ✅ Initialize with default
110
- }
111
- ```
112
-
113
- ## Batching Updates
114
-
115
- Lego batches updates using `requestAnimationFrame`:
116
-
117
- ```js
118
- this.count = 1;
119
- this.count = 2;
120
- this.count = 3;
121
- // Only one re-render happens!
122
- ```
123
-
124
- This prevents unnecessary DOM updates and improves performance.
125
-
126
- ## Update Lifecycle
127
-
128
- 1. **State Change** - You mutate data
129
- 2. **Proxy Intercepts** - Change is detected
130
- 3. **Batch Queue** - Component added to update queue
131
- 4. **requestAnimationFrame** - Browser schedules render
132
- 5. **Re-render** - DOM is updated
133
- 6. **updated() Hook** - Called after render
134
-
135
- ```js
136
- {
137
- count: 0,
138
-
139
- increment() {
140
- console.log('Before:', this.count);
141
- this.count++;
142
- console.log('After:', this.count);
143
- // DOM not updated yet!
144
- },
145
-
146
- updated() {
147
- console.log('DOM updated with:', this.count);
148
- }
149
- }
150
- ```
151
-
152
- ## Global Reactivity
153
-
154
- Lego also supports **Global State** available to all components and the main document.
155
-
156
- ```js
157
- // src/main.js
158
- Lego.globals.isLoggedIn = true;
159
- ```
160
-
161
- For global state to automatically update mustaches in your `index.html`, you must initialize the engine:
162
-
163
- ```js
164
- // Enables global reactivity and the MutationObserver
165
- Lego.init();
166
- ```
167
-
168
- Inside any component, you can access global state via `global`:
169
-
170
- ```html
171
- <p b-show="global.isLoggedIn">Welcome!</p>
172
- ```
173
-
174
- ## Deep Reactivity
175
-
176
- Nested objects are automatically reactive:
177
-
178
- ```js
179
- {
180
- user: {
181
- profile: {
182
- settings: {
183
- theme: 'dark'
184
- }
185
- }
186
- }
187
- }
188
- ```
189
-
190
- ```html
191
- <!-- All reactive -->
192
- <p>[[ user.profile.settings.theme ]]</p>
193
- ```
194
-
195
- ```js
196
- this.user.profile.settings.theme = 'light'; // ✅ Updates DOM
197
- ```
198
-
199
- ## Arrays and Objects
200
-
201
- ### Array Mutations
202
-
203
- All mutating methods trigger updates:
204
-
205
- ```js
206
- this.items.push(newItem);
207
- this.items.pop();
208
- this.items.shift();
209
- this.items.unshift(item);
210
- this.items.splice(index, 1);
211
- this.items.sort();
212
- this.items.reverse();
213
- ```
214
-
215
- ### Non-Mutating Methods
216
-
217
- These don't trigger updates (they return new arrays):
218
-
219
- ```js
220
- const filtered = this.items.filter(x => x.active); // No update
221
- const mapped = this.items.map(x => x.name); // No update
222
- ```
223
-
224
- To make them reactive, assign back:
225
-
226
- ```js
227
- this.items = this.items.filter(x => x.active); // ✅ Triggers update
228
- ```
229
-
230
- Or use mutating equivalents:
231
-
232
- ```js
233
- // Instead of filter
234
- for (let i = this.items.length - 1; i >= 0; i--) {
235
- if (!this.items[i].active) {
236
- this.items.splice(i, 1); // ✅ Reactive
237
- }
238
- }
239
- ```
240
-
241
- ## Object Changes
242
-
243
- ### Adding Properties to Nested Objects
244
-
245
- ```js
246
- this.user.newProp = 'value'; // ✅ Reactive (nested object)
247
- ```
248
-
249
- ### Object.assign()
250
-
251
- ```js
252
- Object.assign(this.user, { name: 'Alice', age: 30 }); // ✅ Reactive
253
- ```
254
-
255
- ## Performance Considerations
256
-
257
- ### Minimize Unnecessary Updates
258
-
259
- Group related changes:
260
-
261
- ```js
262
- // ❌ Bad - 3 separate updates
263
- this.user.name = 'Alice';
264
- this.user.age = 30;
265
- this.user.email = 'alice@example.com';
266
-
267
- // ✅ Better - 1 update
268
- Object.assign(this.user, {
269
- name: 'Alice',
270
- age: 30,
271
- email: 'alice@example.com'
272
- });
273
- ```
274
-
275
- ### Avoid Reactive Overhead for Static Data
276
-
277
- Don't make everything reactive:
278
-
279
- ```js
280
- {
281
- // Reactive data
282
- count: 0,
283
-
284
- // Constants (not reactive, but that's fine)
285
- MAX_COUNT: 100,
286
- API_URL: 'https://api.example.com'
287
- }
288
- ```
289
-
290
- ## Debugging Reactivity
291
-
292
- ### Check if Value Changed
293
-
294
- ```js
295
- {
296
- count: 0,
297
-
298
- updated() {
299
- console.log('Count changed to:', this.count);
300
- }
301
- }
302
- ```
303
-
304
- ### Inspect Proxy
305
-
306
- ```js
307
- console.log(component._studs); // Proxy object
308
- console.log(component._studs.count); // Actual value
309
- ```
310
-
311
- ## Comparing with Other Frameworks
312
-
313
- ### Vue 3
314
-
315
- ```js
316
- // Vue 3
317
- const count = ref(0);
318
- count.value++;
319
-
320
- // Lego
321
- this.count++;
322
- ```
323
-
324
- ### React
325
-
326
- ```js
327
- // React
328
- const [count, setCount] = useState(0);
329
- setCount(count + 1);
330
-
331
- // Lego
332
- this.count++;
333
- ```
334
-
335
- ### Svelte
336
-
337
- ```js
338
- // Svelte
339
- let count = 0;
340
- count++;
341
-
342
- // Lego
343
- this.count++;
344
- ```
345
-
346
- Lego is closest to Svelte's model but uses Proxies instead of compilation.
347
-
348
- ## Advanced Patterns
349
-
350
- ### Watching for Changes
351
-
352
- Use `updated()` hook:
353
-
354
- ```js
355
- {
356
- count: 0,
357
- previousCount: 0,
358
-
359
- updated() {
360
- if (this.count !== this.previousCount) {
361
- console.log('Count changed from', this.previousCount, 'to', this.count);
362
- this.previousCount = this.count;
363
- }
364
- }
365
- }
366
- ```
367
-
368
- ### Computed Properties
369
-
370
- Use methods:
371
-
372
- ```js
373
- {
374
- firstName: 'John',
375
- lastName: 'Doe',
376
-
377
- fullName() {
378
- return `${this.firstName} ${this.lastName}`;
379
- }
380
- }
381
- ```
382
-
383
- ```html
384
- <p>[[ fullName() ]]</p>
385
- ```
386
-
387
- ### Debouncing Updates
388
-
389
- ```js
390
- {
391
- searchQuery: '',
392
- timer: null,
393
-
394
- onInput() {
395
- clearTimeout(this.timer);
396
- this.timer = setTimeout(() => {
397
- this.performSearch();
398
- }, 300);
399
- }
400
- }
401
- ```
402
-
403
- ## Best Practices
404
-
405
- 1. **Initialize all properties** - Define them upfront
406
- 2. **Use array methods** - push(), splice(), etc.
407
- 3. **Batch related changes** - Use Object.assign()
408
- 4. **Keep state flat when possible** - Shallow is faster
409
- 5. **Use methods for computed values** - They're called on every render
410
-
411
- ## Next Steps
412
-
413
- - Learn about [Templating](/guide/templating)
414
- - Explore [Directives](/guide/directives)
415
- - See [reactivity examples](/examples/)