lego-dom 0.0.7 → 0.0.9

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 (147) hide show
  1. package/.github/workflows/deploy-docs.yml +56 -0
  2. package/LICENSE +21 -0
  3. package/README.md +52 -314
  4. package/docs/.vitepress/config.js +107 -0
  5. package/docs/.vitepress/dist/404.html +22 -0
  6. package/docs/.vitepress/dist/api/define.html +35 -0
  7. package/docs/.vitepress/dist/api/directives.html +32 -0
  8. package/docs/.vitepress/dist/api/globals.html +27 -0
  9. package/docs/.vitepress/dist/api/index.html +25 -0
  10. package/docs/.vitepress/dist/api/lifecycle.html +38 -0
  11. package/docs/.vitepress/dist/api/route.html +34 -0
  12. package/docs/.vitepress/dist/api/vite-plugin.html +37 -0
  13. package/docs/.vitepress/dist/assets/api_define.md.UA-ygUnQ.js +11 -0
  14. package/docs/.vitepress/dist/assets/api_define.md.UA-ygUnQ.lean.js +1 -0
  15. package/docs/.vitepress/dist/assets/api_directives.md.BV-D251p.js +8 -0
  16. package/docs/.vitepress/dist/assets/api_directives.md.BV-D251p.lean.js +1 -0
  17. package/docs/.vitepress/dist/assets/api_globals.md.CEznyRAY.js +3 -0
  18. package/docs/.vitepress/dist/assets/api_globals.md.CEznyRAY.lean.js +1 -0
  19. package/docs/.vitepress/dist/assets/api_index.md.IEYUxUIr.js +1 -0
  20. package/docs/.vitepress/dist/assets/api_index.md.IEYUxUIr.lean.js +1 -0
  21. package/docs/.vitepress/dist/assets/api_lifecycle.md.Ccm5xw6-.js +14 -0
  22. package/docs/.vitepress/dist/assets/api_lifecycle.md.Ccm5xw6-.lean.js +1 -0
  23. package/docs/.vitepress/dist/assets/api_route.md.CAHf_KNp.js +10 -0
  24. package/docs/.vitepress/dist/assets/api_route.md.CAHf_KNp.lean.js +1 -0
  25. package/docs/.vitepress/dist/assets/api_vite-plugin.md.DC8Li09k.js +13 -0
  26. package/docs/.vitepress/dist/assets/api_vite-plugin.md.DC8Li09k.lean.js +1 -0
  27. package/docs/.vitepress/dist/assets/app.BfblNDJy.js +1 -0
  28. package/docs/.vitepress/dist/assets/chunks/@localSearchIndexroot.Crdp7-Zp.js +1 -0
  29. package/docs/.vitepress/dist/assets/chunks/VPLocalSearchBox.C18E44rY.js +9 -0
  30. package/docs/.vitepress/dist/assets/chunks/framework.B7OFBR9X.js +19 -0
  31. package/docs/.vitepress/dist/assets/chunks/theme.VX3itTW6.js +2 -0
  32. package/docs/.vitepress/dist/assets/examples_form.md.DQoAgbLR.js +34 -0
  33. package/docs/.vitepress/dist/assets/examples_form.md.DQoAgbLR.lean.js +1 -0
  34. package/docs/.vitepress/dist/assets/examples_index.md.CVJJjXXE.js +28 -0
  35. package/docs/.vitepress/dist/assets/examples_index.md.CVJJjXXE.lean.js +1 -0
  36. package/docs/.vitepress/dist/assets/examples_routing.md.sRnA5RXw.js +338 -0
  37. package/docs/.vitepress/dist/assets/examples_routing.md.sRnA5RXw.lean.js +1 -0
  38. package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DPf9Wm99.js +13 -0
  39. package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DPf9Wm99.lean.js +1 -0
  40. package/docs/.vitepress/dist/assets/examples_todo-app.md.CqF4JaWn.js +297 -0
  41. package/docs/.vitepress/dist/assets/examples_todo-app.md.CqF4JaWn.lean.js +1 -0
  42. package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CjIjusre.js +182 -0
  43. package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CjIjusre.lean.js +1 -0
  44. package/docs/.vitepress/dist/assets/guide_components.md.CMU3iM6R.js +174 -0
  45. package/docs/.vitepress/dist/assets/guide_components.md.CMU3iM6R.lean.js +1 -0
  46. package/docs/.vitepress/dist/assets/guide_contributing.md.Crrv3T_0.js +1 -0
  47. package/docs/.vitepress/dist/assets/guide_contributing.md.Crrv3T_0.lean.js +1 -0
  48. package/docs/.vitepress/dist/assets/guide_directives.md.DFwqvqOv.js +140 -0
  49. package/docs/.vitepress/dist/assets/guide_directives.md.DFwqvqOv.lean.js +1 -0
  50. package/docs/.vitepress/dist/assets/guide_getting-started.md.DtaJPe0i.js +107 -0
  51. package/docs/.vitepress/dist/assets/guide_getting-started.md.DtaJPe0i.lean.js +1 -0
  52. package/docs/.vitepress/dist/assets/guide_index.md.DtJVpLI9.js +2 -0
  53. package/docs/.vitepress/dist/assets/guide_index.md.DtJVpLI9.lean.js +1 -0
  54. package/docs/.vitepress/dist/assets/guide_lifecycle.md.CfY3jlU1.js +304 -0
  55. package/docs/.vitepress/dist/assets/guide_lifecycle.md.CfY3jlU1.lean.js +1 -0
  56. package/docs/.vitepress/dist/assets/guide_quick-start.md.CwdNNA21.js +33 -0
  57. package/docs/.vitepress/dist/assets/guide_quick-start.md.CwdNNA21.lean.js +1 -0
  58. package/docs/.vitepress/dist/assets/guide_reactivity.md.DgTH0MTn.js +135 -0
  59. package/docs/.vitepress/dist/assets/guide_reactivity.md.DgTH0MTn.lean.js +1 -0
  60. package/docs/.vitepress/dist/assets/guide_routing.md.nMB0QOBR.js +193 -0
  61. package/docs/.vitepress/dist/assets/guide_routing.md.nMB0QOBR.lean.js +1 -0
  62. package/docs/.vitepress/dist/assets/guide_sfc.md.BUkWma1z.js +187 -0
  63. package/docs/.vitepress/dist/assets/guide_sfc.md.BUkWma1z.lean.js +1 -0
  64. package/docs/.vitepress/dist/assets/guide_templating.md.XI3uUlYI.js +119 -0
  65. package/docs/.vitepress/dist/assets/guide_templating.md.XI3uUlYI.lean.js +1 -0
  66. package/docs/.vitepress/dist/assets/index.md.M4_o26kF.js +23 -0
  67. package/docs/.vitepress/dist/assets/index.md.M4_o26kF.lean.js +1 -0
  68. package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  69. package/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  70. package/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  71. package/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  72. package/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  73. package/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  74. package/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  75. package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  76. package/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  77. package/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  78. package/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  79. package/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  80. package/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  81. package/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  82. package/docs/.vitepress/dist/assets/style.eycE2Jhw.css +1 -0
  83. package/docs/.vitepress/dist/examples/form.html +58 -0
  84. package/docs/.vitepress/dist/examples/index.html +52 -0
  85. package/docs/.vitepress/dist/examples/routing.html +362 -0
  86. package/docs/.vitepress/dist/examples/sfc-showcase.html +37 -0
  87. package/docs/.vitepress/dist/examples/todo-app.html +321 -0
  88. package/docs/.vitepress/dist/guide/cdn-usage.html +206 -0
  89. package/docs/.vitepress/dist/guide/components.html +198 -0
  90. package/docs/.vitepress/dist/guide/contributing.html +25 -0
  91. package/docs/.vitepress/dist/guide/directives.html +164 -0
  92. package/docs/.vitepress/dist/guide/getting-started.html +131 -0
  93. package/docs/.vitepress/dist/guide/index.html +26 -0
  94. package/docs/.vitepress/dist/guide/lifecycle.html +328 -0
  95. package/docs/.vitepress/dist/guide/quick-start.html +57 -0
  96. package/docs/.vitepress/dist/guide/reactivity.html +159 -0
  97. package/docs/.vitepress/dist/guide/routing.html +217 -0
  98. package/docs/.vitepress/dist/guide/sfc.html +211 -0
  99. package/docs/.vitepress/dist/guide/templating.html +143 -0
  100. package/docs/.vitepress/dist/hashmap.json +1 -0
  101. package/docs/.vitepress/dist/index.html +47 -0
  102. package/docs/.vitepress/dist/logo.svg +38 -0
  103. package/docs/.vitepress/dist/vp-icons.css +1 -0
  104. package/docs/api/define.md +31 -0
  105. package/docs/api/directives.md +42 -0
  106. package/docs/api/globals.md +29 -0
  107. package/docs/api/index.md +29 -0
  108. package/docs/api/lifecycle.md +40 -0
  109. package/docs/api/route.md +37 -0
  110. package/docs/api/vite-plugin.md +58 -0
  111. package/docs/examples/form.md +42 -0
  112. package/docs/examples/index.md +104 -0
  113. package/docs/examples/routing.md +409 -0
  114. package/docs/examples/sfc-showcase.md +34 -0
  115. package/docs/examples/todo-app.md +383 -0
  116. package/docs/guide/cdn-usage.md +320 -0
  117. package/docs/guide/components.md +394 -0
  118. package/docs/guide/contributing.md +32 -0
  119. package/docs/guide/directives.md +430 -0
  120. package/docs/guide/getting-started.md +233 -0
  121. package/docs/guide/index.md +88 -0
  122. package/docs/guide/lifecycle.md +493 -0
  123. package/docs/guide/quick-start.md +46 -0
  124. package/docs/guide/reactivity.md +394 -0
  125. package/docs/guide/routing.md +373 -0
  126. package/docs/guide/sfc.md +381 -0
  127. package/docs/guide/templating.md +383 -0
  128. package/docs/index.md +126 -0
  129. package/docs/public/logo.svg +17 -0
  130. package/examples/vite-app/README.md +71 -0
  131. package/examples/vite-app/index.html +49 -0
  132. package/examples/vite-app/package.json +16 -0
  133. package/examples/vite-app/src/components/greeting-card.lego +41 -0
  134. package/examples/vite-app/src/components/sample-component.lego +75 -0
  135. package/examples/vite-app/src/components/todo-list.lego +242 -0
  136. package/examples/vite-app/src/main.js +11 -0
  137. package/examples/vite-app/vite.config.js +17 -0
  138. package/examples.js +99 -0
  139. package/go.html +117 -0
  140. package/lego.js +2 -0
  141. package/main.js +41 -35
  142. package/package.json +39 -6
  143. package/parse-lego.js +119 -0
  144. package/parse-lego.test.js +107 -0
  145. package/vite-plugin.js +133 -0
  146. package/.ignore/auto.html +0 -135
  147. package/.ignore/test.html +0 -73
@@ -0,0 +1,88 @@
1
+ # What is Lego?
2
+
3
+ LegoDOM is a tiny, zero-dependency JavaScript library for building reactive Web Components directly in the browser.
4
+
5
+ ## The Philosophy
6
+
7
+ LegoDOM is built on a simple belief: **the DOM is not your enemy**.
8
+
9
+ Modern frameworks introduced virtual DOMs and compilation steps to solve problems that arose from trying to make the DOM do things it wasn't designed for. Lego takes a different approach—it embraces the DOM and Web Components as they were intended to be used.
10
+
11
+ ## Key Principles
12
+
13
+ ### 1. Mental Model Simplicity
14
+
15
+ There are no new concepts to learn. If you know:
16
+ - HTML
17
+ - JavaScript objects
18
+ - Basic DOM events
19
+
20
+ You already know Lego.
21
+
22
+ ### 2. No Build Step Required
23
+
24
+ Drop a `<script>` tag in your HTML and you're ready to go. Build tools are optional, not mandatory.
25
+
26
+ ### 3. True Reactivity
27
+
28
+ Change an object → the DOM updates. That's it. No `setState`, no `dispatch`, no `computed properties` to configure.
29
+
30
+ ```js
31
+ // This just works
32
+ component._studs.count++;
33
+ ```
34
+
35
+ ### 4. Web Standards First
36
+
37
+ Lego uses:
38
+ - **Web Components** - Standard custom elements
39
+ - **Shadow DOM** - Native encapsulation
40
+ - **ES6 Proxies** - For reactivity
41
+ - **Template literals** - For templating
42
+
43
+ No proprietary APIs. Everything is built on web standards.
44
+
45
+ ## When to Use Lego
46
+
47
+ ### ✅ Lego is Great For:
48
+
49
+ - **Small to medium applications** where framework overhead isn't worth it
50
+ - **Embedded widgets** that need to work anywhere
51
+ - **Progressive enhancement** of existing sites
52
+ - **Learning** how reactive systems work under the hood
53
+ - **Projects** where you want full control and no dependencies
54
+
55
+ ### ⚠️ Consider Alternatives If:
56
+
57
+ - You need a massive ecosystem of pre-built components
58
+ - Your team is already invested in React/Vue/Angular
59
+ - You need SSR (Server-Side Rendering) out of the box
60
+ - You're building something extremely complex with hundreds of components
61
+
62
+ ## How Small Is It?
63
+
64
+ The core library (`main.js`) is **under 500 lines** of well-commented JavaScript.
65
+
66
+ - **No dependencies** - Zero `node_modules` bloat
67
+ - **~17KB** - Unminified, human-readable code
68
+ - **~6KB** - Minified and gzipped
69
+
70
+ Compare that to:
71
+ - Vue 3: ~33KB (minified + gzipped)
72
+ - React + ReactDOM: ~40KB (minified + gzipped)
73
+ - Angular: ~100KB+ (minified + gzipped)
74
+
75
+ ## What Makes It Different?
76
+
77
+ | Aspect | Lego | Traditional Frameworks |
78
+ |--------|--------|----------------------|
79
+ | **Reactivity** | Direct object mutation | setState / dispatch / ref() |
80
+ | **Templates** | HTML with `{{ }}` | JSX / template syntax |
81
+ | **Styles** | Shadow DOM (native) | CSS-in-JS / scoped CSS |
82
+ | **Build** | Optional | Required |
83
+ | **Learning Curve** | Hours | Days/Weeks |
84
+ |**Philosophy** | Embrace the platform | Abstract the platform |
85
+
86
+ ## Next Steps
87
+
88
+ Ready to dive in? Head to the [Getting Started](/guide/getting-started) guide to build your first component in under 5 minutes.
@@ -0,0 +1,493 @@
1
+ # Lifecycle Hooks
2
+
3
+ Learn about component lifecycle hooks in Lego.
4
+
5
+ ## Overview
6
+
7
+ Components have three lifecycle hooks:
8
+
9
+ - `mounted()` - Called after component is added to DOM
10
+ - `updated()` - Called after state changes and re-render
11
+ - `unmounted()` - Called when component is removed from DOM
12
+
13
+ ## mounted()
14
+
15
+ Called once when the component is first attached to the DOM.
16
+
17
+ ### Usage
18
+
19
+ ```js
20
+ {
21
+ data: null,
22
+
23
+ mounted() {
24
+ console.log('Component is now in the DOM');
25
+ this.fetchData();
26
+ },
27
+
28
+ async fetchData() {
29
+ this.data = await fetch('/api/data').then(r => r.json());
30
+ }
31
+ }
32
+ ```
33
+
34
+ ### Common Use Cases
35
+
36
+ **Fetch Data:**
37
+ ```js
38
+ {
39
+ mounted() {
40
+ this.loadUserData();
41
+ }
42
+ }
43
+ ```
44
+
45
+ **Start Timers:**
46
+ ```js
47
+ {
48
+ timer: null,
49
+
50
+ mounted() {
51
+ this.timer = setInterval(() => {
52
+ this.tick();
53
+ }, 1000);
54
+ }
55
+ }
56
+ ```
57
+
58
+ **Add Event Listeners:**
59
+ ```js
60
+ {
61
+ mounted() {
62
+ window.addEventListener('resize', this.handleResize.bind(this));
63
+ }
64
+ }
65
+ ```
66
+
67
+ **Initialize Third-Party Libraries:**
68
+ ```js
69
+ {
70
+ mounted() {
71
+ this.chart = new Chart(this.$element.shadowRoot.querySelector('canvas'), {
72
+ type: 'bar',
73
+ data: this.chartData
74
+ });
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## updated()
80
+
81
+ Called after every state change and re-render.
82
+
83
+ ### Usage
84
+
85
+ ```js
86
+ {
87
+ count: 0,
88
+
89
+ updated() {
90
+ console.log('Component re-rendered, count is:', this.count);
91
+ }
92
+ }
93
+ ```
94
+
95
+ ### Common Use Cases
96
+
97
+ **Track Changes:**
98
+ ```js
99
+ {
100
+ previousValue: null,
101
+ value: 0,
102
+
103
+ updated() {
104
+ if (this.value !== this.previousValue) {
105
+ console.log('Value changed from', this.previousValue, 'to', this.value);
106
+ this.previousValue = this.value;
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ **Update Third-Party Libraries:**
113
+ ```js
114
+ {
115
+ chartData: [],
116
+
117
+ updated() {
118
+ if (this.chart) {
119
+ this.chart.data = this.chartData;
120
+ this.chart.update();
121
+ }
122
+ }
123
+ }
124
+ ```
125
+
126
+ **Analytics:**
127
+ ```js
128
+ {
129
+ updated() {
130
+ if (window.gtag) {
131
+ gtag('event', 'state_change', {
132
+ component: 'my-component',
133
+ count: this.count
134
+ });
135
+ }
136
+ }
137
+ }
138
+ ```
139
+
140
+ ::: warning Performance
141
+ `updated()` runs on every state change. Keep it lightweight!
142
+ :::
143
+
144
+ ## unmounted()
145
+
146
+ Called when the component is removed from the DOM.
147
+
148
+ ### Usage
149
+
150
+ ```js
151
+ {
152
+ unmounted() {
153
+ console.log('Component is being removed');
154
+ this.cleanup();
155
+ }
156
+ }
157
+ ```
158
+
159
+ ### Common Use Cases
160
+
161
+ **Clear Timers:**
162
+ ```js
163
+ {
164
+ timer: null,
165
+
166
+ mounted() {
167
+ this.timer = setInterval(() => this.tick(), 1000);
168
+ },
169
+
170
+ unmounted() {
171
+ clearInterval(this.timer);
172
+ }
173
+ }
174
+ ```
175
+
176
+ **Remove Event Listeners:**
177
+ ```js
178
+ {
179
+ handleResize: null,
180
+
181
+ mounted() {
182
+ this.handleResize = () => {
183
+ this.width = window.innerWidth;
184
+ };
185
+ window.addEventListener('resize', this.handleResize);
186
+ },
187
+
188
+ unmounted() {
189
+ window.removeEventListener('resize', this.handleResize);
190
+ }
191
+ }
192
+ ```
193
+
194
+ **Destroy Third-Party Instances:**
195
+ ```js
196
+ {
197
+ chart: null,
198
+
199
+ mounted() {
200
+ this.chart = new Chart(...);
201
+ },
202
+
203
+ unmounted() {
204
+ if (this.chart) {
205
+ this.chart.destroy();
206
+ }
207
+ }
208
+ }
209
+ ```
210
+
211
+ **Cancel Pending Requests:**
212
+ ```js
213
+ {
214
+ controller: null,
215
+
216
+ async fetchData() {
217
+ this.controller = new AbortController();
218
+ try {
219
+ const data = await fetch('/api/data', {
220
+ signal: this.controller.signal
221
+ }).then(r => r.json());
222
+ this.data = data;
223
+ } catch (err) {
224
+ if (err.name === 'AbortError') {
225
+ console.log('Fetch aborted');
226
+ }
227
+ }
228
+ },
229
+
230
+ unmounted() {
231
+ if (this.controller) {
232
+ this.controller.abort();
233
+ }
234
+ }
235
+ }
236
+ ```
237
+
238
+ ## Lifecycle Flow
239
+
240
+ ```
241
+ 1. Component created (HTML element instantiated)
242
+ 2. Shadow DOM attached
243
+ 3. Template rendered
244
+ 4. mounted() hook called → Component is interactive
245
+ 5. User interaction / state change
246
+ 6. Component re-rendered
247
+ 7. updated() hook called
248
+ 8. (repeat steps 5-7 as needed)
249
+ 9. Component removed from DOM
250
+ 10. unmounted() hook called → Cleanup
251
+ ```
252
+
253
+ ## Complete Example
254
+
255
+ ```js
256
+ {
257
+ // State
258
+ count: 0,
259
+ timer: null,
260
+ data: null,
261
+
262
+ // Lifecycle: Component mounted
263
+ mounted() {
264
+ console.log('[mounted] Component added to DOM');
265
+
266
+ // Fetch initial data
267
+ this.fetchData();
268
+
269
+ // Start interval
270
+ this.timer = setInterval(() => {
271
+ this.count++;
272
+ }, 1000);
273
+
274
+ // Add event listener
275
+ this.handleKeyPress = (e) => {
276
+ if (e.key === 'Escape') {
277
+ this.reset();
278
+ }
279
+ };
280
+ document.addEventListener('keydown', this.handleKeyPress);
281
+ },
282
+
283
+ // Lifecycle: Component updated
284
+ updated() {
285
+ console.log('[updated] Component re-rendered, count:', this.count);
286
+
287
+ // Log when count reaches milestone
288
+ if (this.count % 10 === 0) {
289
+ console.log('Milestone:', this.count);
290
+ }
291
+ },
292
+
293
+ // Lifecycle: Component unmounted
294
+ unmounted() {
295
+ console.log('[unmounted] Component removed from DOM');
296
+
297
+ // Clear interval
298
+ if (this.timer) {
299
+ clearInterval(this.timer);
300
+ }
301
+
302
+ // Remove event listener
303
+ document.removeEventListener('keydown', this.handleKeyPress);
304
+ },
305
+
306
+ // Methods
307
+ async fetchData() {
308
+ this.data = await fetch('/api/data').then(r => r.json());
309
+ },
310
+
311
+ reset() {
312
+ this.count = 0;
313
+ }
314
+ }
315
+ ```
316
+
317
+ ## Best Practices
318
+
319
+ ### 1. Initialize in mounted()
320
+
321
+ Don't fetch data or start timers in the state object:
322
+
323
+ ```js
324
+ // ❌ Bad
325
+ {
326
+ data: fetch('/api/data').then(r => r.json()), // Executes immediately
327
+ timer: setInterval(() => {}, 1000) // Starts before component exists
328
+ }
329
+
330
+ // ✅ Good
331
+ {
332
+ data: null,
333
+ timer: null,
334
+ mounted() {
335
+ this.fetchData();
336
+ this.timer = setInterval(() => {}, 1000);
337
+ }
338
+ }
339
+ ```
340
+
341
+ ### 2. Always Clean Up
342
+
343
+ If you start something in `mounted()`, stop it in `unmounted()`:
344
+
345
+ ```js
346
+ {
347
+ mounted() {
348
+ this.timer = setInterval(...);
349
+ window.addEventListener('resize', this.handleResize);
350
+ },
351
+
352
+ unmounted() {
353
+ clearInterval(this.timer); // ✅
354
+ window.removeEventListener('resize', this.handleResize); // ✅
355
+ }
356
+ }
357
+ ```
358
+
359
+ ### 3. Keep updated() Light
360
+
361
+ `updated()` runs frequently—avoid heavy operations:
362
+
363
+ ```js
364
+ // ❌ Bad
365
+ {
366
+ updated() {
367
+ this.expensiveCalculation(); // Runs on every change!
368
+ }
369
+ }
370
+
371
+ // ✅ Good
372
+ {
373
+ updated() {
374
+ // Only log or track
375
+ console.log('State changed');
376
+ }
377
+ }
378
+ ```
379
+
380
+ ### 4. Guard Against Errors
381
+
382
+ ```js
383
+ {
384
+ unmounted() {
385
+ // Check before clearing
386
+ if (this.timer) {
387
+ clearInterval(this.timer);
388
+ }
389
+
390
+ // Check before destroying
391
+ if (this.chart) {
392
+ this.chart.destroy();
393
+ }
394
+ }
395
+ }
396
+ ```
397
+
398
+ ## Common Patterns
399
+
400
+ ### Loading State
401
+
402
+ ```js
403
+ {
404
+ loading: true,
405
+ data: null,
406
+
407
+ async mounted() {
408
+ try {
409
+ this.data = await fetch('/api/data').then(r => r.json());
410
+ } finally {
411
+ this.loading = false;
412
+ }
413
+ }
414
+ }
415
+ ```
416
+
417
+ ### Polling
418
+
419
+ ```js
420
+ {
421
+ pollInterval: null,
422
+
423
+ mounted() {
424
+ this.poll();
425
+ this.pollInterval = setInterval(() => this.poll(), 5000);
426
+ },
427
+
428
+ async poll() {
429
+ this.data = await fetch('/api/status').then(r => r.json());
430
+ },
431
+
432
+ unmounted() {
433
+ clearInterval(this.pollInterval);
434
+ }
435
+ }
436
+ ```
437
+
438
+ ### Scroll Position
439
+
440
+ ```js
441
+ {
442
+ scrollY: 0,
443
+ handleScroll: null,
444
+
445
+ mounted() {
446
+ this.handleScroll = () => {
447
+ this.scrollY = window.scrollY;
448
+ };
449
+ window.addEventListener('scroll', this.handleScroll);
450
+ },
451
+
452
+ unmounted() {
453
+ window.removeEventListener('scroll', this.handleScroll);
454
+ }
455
+ }
456
+ ```
457
+
458
+ ### Animation
459
+
460
+ ```js
461
+ {
462
+ mounted() {
463
+ const el = this.$element.shadowRoot.querySelector('.animated');
464
+ el.classList.add('fade-in');
465
+ }
466
+ }
467
+ ```
468
+
469
+ ## Debugging Lifecycle
470
+
471
+ Log lifecycle events to understand component behavior:
472
+
473
+ ```js
474
+ {
475
+ mounted() {
476
+ console.log('[LIFECYCLE] mounted');
477
+ },
478
+
479
+ updated() {
480
+ console.log('[LIFECYCLE] updated');
481
+ },
482
+
483
+ unmounted() {
484
+ console.log('[LIFECYCLE] unmounted');
485
+ }
486
+ }
487
+ ```
488
+
489
+ ## Next Steps
490
+
491
+ - See [lifecycle examples](/examples/)
492
+ - Learn about [component patterns](/guide/components)
493
+ - Explore [state management](/guide/reactivity)
@@ -0,0 +1,46 @@
1
+ # Quick Start
2
+
3
+ The fastest way to get started with Lego is using the CDN. No build tools required!
4
+
5
+ ## 1. Create an HTML file
6
+
7
+ ```html
8
+ <!DOCTYPE html>
9
+ <html lang="en">
10
+ <head>
11
+ <meta charset="UTF-8">
12
+ <title>Lego Quick Start</title>
13
+ </head>
14
+ <body>
15
+ <!-- 2. Use your component -->
16
+ <hello-world></hello-world>
17
+
18
+ <!-- 3. Define the template -->
19
+ <template b-id="hello-world">
20
+ <style>
21
+ h1 { color: #646cff; }
22
+ </style>
23
+ <h1>Hello, {{ name }}!</h1>
24
+ <button @click="toggle()">Toggle Name</button>
25
+ </template>
26
+
27
+ <!-- 4. Load Lego -->
28
+ <script src="https://unpkg.com/lego-dom/main.js"></script>
29
+
30
+ <!-- 5. Define logic (Optional) -->
31
+ <script>
32
+ document.querySelector('hello-world').state = {
33
+ name: 'World',
34
+ toggle() {
35
+ this.name = this.name === 'World' ? 'Lego' : 'World';
36
+ }
37
+ };
38
+ </script>
39
+ </body>
40
+ </html>
41
+ ```
42
+
43
+ ## Next Steps
44
+
45
+ - Explore [Core Concepts](/guide/components)
46
+ - Check out the [API Reference](/api/)