lego-dom 1.0.0 → 1.3.4

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 (74) hide show
  1. package/.legodom +87 -0
  2. package/CHANGELOG.md +87 -3
  3. package/cdn.html +10 -5
  4. package/docs/.vitepress/config.js +23 -7
  5. package/docs/api/config.md +95 -0
  6. package/docs/api/define.md +29 -2
  7. package/docs/api/directives.md +10 -2
  8. package/docs/api/index.md +1 -0
  9. package/docs/contributing/01-welcome.md +2 -0
  10. package/docs/contributing/02-registry.md +37 -3
  11. package/docs/contributing/06-init.md +13 -2
  12. package/docs/contributing/07-observer.md +3 -0
  13. package/docs/contributing/08-snap.md +15 -1
  14. package/docs/contributing/10-studs.md +3 -1
  15. package/docs/contributing/11-scanner.md +13 -0
  16. package/docs/contributing/12-render.md +32 -10
  17. package/docs/contributing/13-directives.md +19 -1
  18. package/docs/contributing/14-events.md +1 -1
  19. package/docs/contributing/15-router.md +49 -1
  20. package/docs/contributing/16-state.md +9 -10
  21. package/docs/contributing/17-legodom.md +1 -8
  22. package/docs/contributing/index.md +23 -4
  23. package/docs/examples/form.md +1 -1
  24. package/docs/examples/index.md +3 -3
  25. package/docs/examples/routing.md +10 -10
  26. package/docs/examples/sfc-showcase.md +1 -1
  27. package/docs/examples/todo-app.md +7 -7
  28. package/docs/guide/cdn-usage.md +44 -18
  29. package/docs/guide/components.md +18 -12
  30. package/docs/guide/directives.md +131 -22
  31. package/docs/guide/directory-structure.md +248 -0
  32. package/docs/guide/faq.md +210 -0
  33. package/docs/guide/getting-started.md +14 -10
  34. package/docs/guide/index.md +1 -1
  35. package/docs/guide/lifecycle.md +32 -0
  36. package/docs/guide/quick-start.md +4 -4
  37. package/docs/guide/reactivity.md +2 -2
  38. package/docs/guide/routing.md +69 -8
  39. package/docs/guide/server-side.md +134 -0
  40. package/docs/guide/sfc.md +96 -13
  41. package/docs/guide/templating.md +62 -57
  42. package/docs/index.md +9 -9
  43. package/docs/router/basic-routing.md +8 -8
  44. package/docs/router/cold-entry.md +2 -2
  45. package/docs/router/history.md +7 -7
  46. package/docs/router/index.md +1 -1
  47. package/docs/router/resolver.md +5 -5
  48. package/docs/router/surgical-swaps.md +5 -5
  49. package/docs/tutorial/01-project-setup.md +152 -0
  50. package/docs/tutorial/02-your-first-component.md +226 -0
  51. package/docs/tutorial/03-adding-routes.md +279 -0
  52. package/docs/tutorial/04-multi-page-app.md +329 -0
  53. package/docs/tutorial/05-state-and-globals.md +285 -0
  54. package/docs/tutorial/index.md +40 -0
  55. package/examples/vite-app/index.html +1 -0
  56. package/examples/vite-app/src/app.js +2 -2
  57. package/examples/vite-app/src/components/side-menu.lego +46 -0
  58. package/examples/vite-app/vite.config.js +2 -1
  59. package/main.js +261 -72
  60. package/main.min.js +7 -0
  61. package/monitoring-plugin.js +111 -0
  62. package/package.json +4 -2
  63. package/parse-lego.js +49 -22
  64. package/tests/error.test.js +74 -0
  65. package/tests/main.test.js +2 -2
  66. package/tests/memory.test.js +68 -0
  67. package/tests/monitoring.test.js +74 -0
  68. package/tests/naming.test.js +74 -0
  69. package/tests/parse-lego.test.js +2 -2
  70. package/tests/security.test.js +67 -0
  71. package/tests/server.test.js +114 -0
  72. package/tests/syntax.test.js +67 -0
  73. package/vite-plugin.js +3 -2
  74. package/docs/guide/contributing.md +0 -32
@@ -0,0 +1,285 @@
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>
@@ -0,0 +1,40 @@
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
+ :::
@@ -32,6 +32,7 @@
32
32
 
33
33
  <body>
34
34
  <app-navbar></app-navbar>
35
+ <side-menu></side-menu>
35
36
  <lego-router id="app-outlet"></lego-router>
36
37
  <aside id="outside-router"></aside>
37
38
 
@@ -1,8 +1,8 @@
1
1
  // Import Tailwind CSS
2
2
  import './app.css';
3
3
 
4
- // Import Lego core
5
- import { Lego } from 'lego-dom/main.js';
4
+ // Import Lego core (local for testing)
5
+ import { Lego } from '../../../lego.js';
6
6
 
7
7
  // Import virtual module that auto-discovers and registers all .lego components
8
8
  import registerComponents from 'virtual:lego-components';
@@ -0,0 +1,46 @@
1
+ <style>
2
+ /* @import 'https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:wght@400;700&display=swap'; */
3
+ self {
4
+ display: flex;
5
+ flex-direction: column;
6
+ align-items: center;
7
+ justify-content: center;
8
+ }
9
+ .tooltipped:hover .tooltip {
10
+ visibility: visible;
11
+ }
12
+ .tooltip {
13
+ visibility: hidden;
14
+ width: 120px;
15
+ background-color: black;
16
+ color: #fff;
17
+ text-align: center;
18
+ border-radius: 5px;
19
+ padding: 5px 0;
20
+ position: absolute;
21
+ z-index: 1;
22
+ bottom: 125%;
23
+ left: 50%;
24
+ margin-left: -60px;
25
+ }
26
+ </style>
27
+
28
+ <template>
29
+ <div>
30
+ <span b-for="menu in [
31
+ { icon: 'home', name: 'Home' },
32
+ { icon: 'mail', name: 'Mail' },
33
+ { icon: 'calendar', name: 'Calendar' },
34
+ { icon: 'person', name: 'Profile' },
35
+ ]">
36
+ <p>[[ menu.name ]]</p>
37
+ </span>
38
+ </div>
39
+ <p>[[ name ]]</p>
40
+ </template>
41
+
42
+ <script>
43
+ export default {
44
+ name: 'side-menu'
45
+ }
46
+ </script>
@@ -9,7 +9,8 @@ export default defineConfig({
9
9
  plugins: [
10
10
  legoPlugin({
11
11
  componentsDir: './src/components',
12
- include: ['**/*.lego']
12
+ include: ['**/*.lego'],
13
+ importPath: 'lego-dom/main.js' // Use the alias defined below
13
14
  }),
14
15
  tailwindcss()
15
16
  ],