lego-dom 0.0.5 → 0.0.8

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 (143) hide show
  1. package/.github/workflows/deploy-docs.yml +56 -0
  2. package/LICENSE +21 -0
  3. package/README.md +298 -355
  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.DOjt7AV0.js +3 -0
  18. package/docs/.vitepress/dist/assets/api_globals.md.DOjt7AV0.lean.js +1 -0
  19. package/docs/.vitepress/dist/assets/api_index.md.OS6h01ct.js +1 -0
  20. package/docs/.vitepress/dist/assets/api_index.md.OS6h01ct.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.DNn9VhL5.js +13 -0
  26. package/docs/.vitepress/dist/assets/api_vite-plugin.md.DNn9VhL5.lean.js +1 -0
  27. package/docs/.vitepress/dist/assets/app.BG5s3B0P.js +1 -0
  28. package/docs/.vitepress/dist/assets/chunks/@localSearchIndexroot.DQmuWC2Z.js +1 -0
  29. package/docs/.vitepress/dist/assets/chunks/VPLocalSearchBox.BO-PSxt1.js +9 -0
  30. package/docs/.vitepress/dist/assets/chunks/framework.B7OFBR9X.js +19 -0
  31. package/docs/.vitepress/dist/assets/chunks/theme.DA-iSa9B.js +2 -0
  32. package/docs/.vitepress/dist/assets/examples_form.md.B3stGKbu.js +34 -0
  33. package/docs/.vitepress/dist/assets/examples_form.md.B3stGKbu.lean.js +1 -0
  34. package/docs/.vitepress/dist/assets/examples_index.md.BDEG_D4J.js +30 -0
  35. package/docs/.vitepress/dist/assets/examples_index.md.BDEG_D4J.lean.js +1 -0
  36. package/docs/.vitepress/dist/assets/examples_routing.md.bqZ9DjDK.js +338 -0
  37. package/docs/.vitepress/dist/assets/examples_routing.md.bqZ9DjDK.lean.js +1 -0
  38. package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DLXaUiop.js +13 -0
  39. package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DLXaUiop.lean.js +1 -0
  40. package/docs/.vitepress/dist/assets/examples_todo-app.md.D5RhZoo5.js +297 -0
  41. package/docs/.vitepress/dist/assets/examples_todo-app.md.D5RhZoo5.lean.js +1 -0
  42. package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CAjf03Lr.js +182 -0
  43. package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CAjf03Lr.lean.js +1 -0
  44. package/docs/.vitepress/dist/assets/guide_components.md.BIFWF1Hc.js +174 -0
  45. package/docs/.vitepress/dist/assets/guide_components.md.BIFWF1Hc.lean.js +1 -0
  46. package/docs/.vitepress/dist/assets/guide_contributing.md.BgbUN-Mr.js +1 -0
  47. package/docs/.vitepress/dist/assets/guide_contributing.md.BgbUN-Mr.lean.js +1 -0
  48. package/docs/.vitepress/dist/assets/guide_directives.md.Bi3ynu1d.js +140 -0
  49. package/docs/.vitepress/dist/assets/guide_directives.md.Bi3ynu1d.lean.js +1 -0
  50. package/docs/.vitepress/dist/assets/guide_getting-started.md.2Nr1lp2z.js +107 -0
  51. package/docs/.vitepress/dist/assets/guide_getting-started.md.2Nr1lp2z.lean.js +1 -0
  52. package/docs/.vitepress/dist/assets/guide_index.md.GvZq_Yf2.js +2 -0
  53. package/docs/.vitepress/dist/assets/guide_index.md.GvZq_Yf2.lean.js +1 -0
  54. package/docs/.vitepress/dist/assets/guide_lifecycle.md.B28j1OzS.js +304 -0
  55. package/docs/.vitepress/dist/assets/guide_lifecycle.md.B28j1OzS.lean.js +1 -0
  56. package/docs/.vitepress/dist/assets/guide_quick-start.md.CNk3VGTF.js +33 -0
  57. package/docs/.vitepress/dist/assets/guide_quick-start.md.CNk3VGTF.lean.js +1 -0
  58. package/docs/.vitepress/dist/assets/guide_reactivity.md.CVsaMaPv.js +135 -0
  59. package/docs/.vitepress/dist/assets/guide_reactivity.md.CVsaMaPv.lean.js +1 -0
  60. package/docs/.vitepress/dist/assets/guide_routing.md.DSpDP25o.js +193 -0
  61. package/docs/.vitepress/dist/assets/guide_routing.md.DSpDP25o.lean.js +1 -0
  62. package/docs/.vitepress/dist/assets/guide_sfc.md.CVUP66tS.js +187 -0
  63. package/docs/.vitepress/dist/assets/guide_sfc.md.CVUP66tS.lean.js +1 -0
  64. package/docs/.vitepress/dist/assets/guide_templating.md.BgCGe4aa.js +119 -0
  65. package/docs/.vitepress/dist/assets/guide_templating.md.BgCGe4aa.lean.js +1 -0
  66. package/docs/.vitepress/dist/assets/index.md.xV1taCED.js +23 -0
  67. package/docs/.vitepress/dist/assets/index.md.xV1taCED.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 +368 -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 +38 -0
  130. package/examples/vite-app/README.md +71 -0
  131. package/examples/vite-app/index.html +45 -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/main.js +11 -0
  136. package/examples/vite-app/vite.config.js +16 -0
  137. package/examples.js +99 -0
  138. package/package.json +34 -7
  139. package/parse-lego.js +119 -0
  140. package/parse-lego.test.js +107 -0
  141. package/vite-plugin.js +133 -0
  142. package/.ignore/auto.html +0 -135
  143. package/.ignore/test.html +0 -73
@@ -0,0 +1,383 @@
1
+ # Templating
2
+
3
+ Learn about LegoJS templating features and syntax.
4
+
5
+ ## Interpolation
6
+
7
+ Use `{{ }}` to insert dynamic content:
8
+
9
+ ### Simple Values
10
+
11
+ ```html
12
+ <p>{{ message }}</p>
13
+ <h1>{{ title }}</h1>
14
+ <span>{{ count }}</span>
15
+ ```
16
+
17
+ ### Expressions
18
+
19
+ ```html
20
+ <p>{{ count * 2 }}</p>
21
+ <span>{{ price.toFixed(2) }}</span>
22
+ <div>{{ firstName + ' ' + lastName }}</div>
23
+ ```
24
+
25
+ ### Method Calls
26
+
27
+ ```html
28
+ <p>{{ formatDate(timestamp) }}</p>
29
+ <span>{{ calculateTotal() }}</span>
30
+ <div>{{ getUsername() }}</div>
31
+ ```
32
+
33
+ ### Conditional (Ternary)
34
+
35
+ ```html
36
+ <p>{{ age >= 18 ? 'Adult' : 'Minor' }}</p>
37
+ <span>{{ isOnline ? '🟢 Online' : '🔴 Offline' }}</span>
38
+ <div>{{ items.length > 0 ? items.length + ' items' : 'Empty' }}</div>
39
+ ```
40
+
41
+ ## Attribute Binding
42
+
43
+ Interpolate in any attribute:
44
+
45
+ ### Simple Attributes
46
+
47
+ ```html
48
+ <img src="/avatars/{{ userId }}.png" alt="{{ username }}">
49
+ <a href="/user/{{ userId }}">{{ username }}</a>
50
+ <input placeholder="{{ defaultText }}">
51
+ ```
52
+
53
+ ### Class Names
54
+
55
+ ```html
56
+ <div class="card {{ isActive ? 'active' : '' }}">...</div>
57
+ <button class="{{ isDisabled ? 'disabled' : 'enabled' }}">...</button>
58
+ <li class="item status-{{ status }}">...</li>
59
+ ```
60
+
61
+ ### Data Attributes
62
+
63
+ ```html
64
+ <div data-id="{{ itemId }}" data-type="{{ itemType }}">...</div>
65
+ ```
66
+
67
+ ### Style (Inline)
68
+
69
+ ```html
70
+ <div style="color: {{ textColor }}; background: {{ bgColor }}">...</div>
71
+ ```
72
+
73
+ ## Escaping
74
+
75
+ LegoJS automatically escapes HTML to prevent XSS:
76
+
77
+ ```js
78
+ {
79
+ userInput: '<script>alert("XSS")</script>'
80
+ }
81
+ ```
82
+
83
+ ```html
84
+ <p>{{ userInput }}</p>
85
+ <!-- Renders as: &lt;script&gt;alert("XSS")&lt;/script&gt; -->
86
+ ```
87
+
88
+ **There is no way to render raw HTML.** This is by design—for security.
89
+
90
+ ## Whitespace
91
+
92
+ Templates preserve whitespace:
93
+
94
+ ```html
95
+ <p>
96
+ {{ message }}
97
+ </p>
98
+ <!-- Renders with newlines and indentation -->
99
+ ```
100
+
101
+ Trim manually if needed:
102
+
103
+ ```html
104
+ <p>{{ message.trim() }}</p>
105
+ ```
106
+
107
+ ## Context
108
+
109
+ Inside `{{ }}`, you have access to:
110
+
111
+ ### Component State (`this`)
112
+
113
+ ```html
114
+ <p>{{ count }}</p> <!-- this.count -->
115
+ <span>{{ user.name }}</span> <!-- this.user.name -->
116
+ ```
117
+
118
+ ### Methods
119
+
120
+ ```html
121
+ <p>{{ formatDate(timestamp) }}</p>
122
+ <div>{{ calculateTotal() }}</div>
123
+ ```
124
+
125
+ ### Special Keywords
126
+
127
+ - `global` - Access `Lego.globals`
128
+ - `event` - In event handlers
129
+ - `self` - Reference to component element (rare)
130
+
131
+ ```html
132
+ <p>{{ global.user.name }}</p>
133
+ <button @click="console.log(event)">Click</button>
134
+ ```
135
+
136
+ ## Complex Examples
137
+
138
+ ### Formatting Currency
139
+
140
+ ```js
141
+ {
142
+ price: 29.99,
143
+ formatCurrency(value) {
144
+ return '$' + value.toFixed(2);
145
+ }
146
+ }
147
+ ```
148
+
149
+ ```html
150
+ <p>Price: {{ formatCurrency(price) }}</p>
151
+ ```
152
+
153
+ ### Date Formatting
154
+
155
+ ```js
156
+ {
157
+ timestamp: Date.now(),
158
+ formatDate(ts) {
159
+ return new Date(ts).toLocaleDateString();
160
+ }
161
+ }
162
+ ```
163
+
164
+ ```html
165
+ <time>{{ formatDate(timestamp) }}</time>
166
+ ```
167
+
168
+ ### Pluralization
169
+
170
+ ```js
171
+ {
172
+ items: ['apple', 'banana'],
173
+ plural(count, singular, plural) {
174
+ return count === 1 ? singular : plural;
175
+ }
176
+ }
177
+ ```
178
+
179
+ ```html
180
+ <p>{{ items.length }} {{ plural(items.length, 'item', 'items') }}</p>
181
+ ```
182
+
183
+ ### Truncation
184
+
185
+ ```js
186
+ {
187
+ description: 'Very long text...',
188
+ truncate(text, length) {
189
+ return text.length > length
190
+ ? text.slice(0, length) + '...'
191
+ : text;
192
+ }
193
+ }
194
+ ```
195
+
196
+ ```html
197
+ <p>{{ truncate(description, 100) }}</p>
198
+ ```
199
+
200
+ ## Limitations
201
+
202
+ ### No Statements
203
+
204
+ Can't use statements—only expressions:
205
+
206
+ ```html
207
+ <!-- ❌ Doesn't work -->
208
+ <p>{{ if (condition) { return 'yes'; } }}</p>
209
+ <p>{{ for (let i = 0; i < 10; i++) { } }}</p>
210
+
211
+ <!-- ✅ Use ternary or methods -->
212
+ <p>{{ condition ? 'yes' : 'no' }}</p>
213
+ <p>{{ renderList() }}</p>
214
+ ```
215
+
216
+ ### No Declarations
217
+
218
+ Can't declare variables:
219
+
220
+ ```html
221
+ <!-- ❌ Doesn't work -->
222
+ <p>{{ const total = price * qty; total }}</p>
223
+
224
+ <!-- ✅ Use methods -->
225
+ <p>{{ getTotal() }}</p>
226
+ ```
227
+
228
+ ```js
229
+ {
230
+ getTotal() {
231
+ const total = this.price * this.qty;
232
+ return total;
233
+ }
234
+ }
235
+ ```
236
+
237
+ ## Best Practices
238
+
239
+ ### 1. Keep Templates Simple
240
+
241
+ If logic is complex, use methods:
242
+
243
+ ```html
244
+ <!-- ❌ Too complex -->
245
+ <p>{{ items.filter(x => x.active).map(x => x.name).join(', ') }}</p>
246
+
247
+ <!-- ✅ Better -->
248
+ <p>{{ getActiveNames() }}</p>
249
+ ```
250
+
251
+ ```js
252
+ {
253
+ getActiveNames() {
254
+ return this.items
255
+ .filter(x => x.active)
256
+ .map(x => x.name)
257
+ .join(', ');
258
+ }
259
+ }
260
+ ```
261
+
262
+ ### 2. Format in Methods
263
+
264
+ Don't put formatting logic in templates:
265
+
266
+ ```html
267
+ <!-- ❌ Messy -->
268
+ <p>${{ (price * 1.2).toFixed(2) }}</p>
269
+
270
+ <!-- ✅ Clean -->
271
+ <p>{{ formatPrice(price) }}</p>
272
+ ```
273
+
274
+ ### 3. Avoid Side Effects
275
+
276
+ Don't mutate state in templates:
277
+
278
+ ```html
279
+ <!-- ❌ Bad -->
280
+ <p>{{ count++ }}</p>
281
+
282
+ <!-- ✅ Good -->
283
+ <p>{{ count }}</p>
284
+ <button @click="count++">Increment</button>
285
+ ```
286
+
287
+ ### 4. Use Descriptive Method Names
288
+
289
+ ```js
290
+ {
291
+ // ✅ Clear purpose
292
+ formatCurrency(value) { ... },
293
+ calculateTax(amount) { ... },
294
+ isValidEmail(email) { ... }
295
+ }
296
+ ```
297
+
298
+ ## Performance Tips
299
+
300
+ ### Cache Computed Values
301
+
302
+ If a calculation is expensive, cache it:
303
+
304
+ ```js
305
+ {
306
+ items: [],
307
+ _cachedTotal: null,
308
+
309
+ total() {
310
+ if (this._cachedTotal === null) {
311
+ this._cachedTotal = this.items.reduce((sum, x) => sum + x.price, 0);
312
+ }
313
+ return this._cachedTotal;
314
+ },
315
+
316
+ updated() {
317
+ this._cachedTotal = null; // Invalidate cache
318
+ }
319
+ }
320
+ ```
321
+
322
+ ### Avoid Heavy Calculations
323
+
324
+ ```html
325
+ <!-- ❌ Runs on every render -->
326
+ <p>{{ expensiveCalculation() }}</p>
327
+
328
+ <!-- ✅ Calculate once, store result -->
329
+ <p>{{ cachedResult }}</p>
330
+ ```
331
+
332
+ ```js
333
+ {
334
+ cachedResult: null,
335
+ mounted() {
336
+ this.cachedResult = this.expensiveCalculation();
337
+ }
338
+ }
339
+ ```
340
+
341
+ ## Common Patterns
342
+
343
+ ### Show/Hide Based on Condition
344
+
345
+ ```html
346
+ <p b-if="user">Welcome, {{ user.name }}!</p>
347
+ <p b-if="!user">Please log in</p>
348
+ ```
349
+
350
+ ### List with Index
351
+
352
+ ```html
353
+ <ul>
354
+ <li b-for="item in items">
355
+ #{{ $index + 1 }}: {{ item.name }}
356
+ </li>
357
+ </ul>
358
+ ```
359
+
360
+ ### Conditional Classes
361
+
362
+ ```html
363
+ <div class="item {{ item.active ? 'active' : '' }} {{ item.featured ? 'featured' : '' }}">
364
+ {{ item.name }}
365
+ </div>
366
+ ```
367
+
368
+ ### Dynamic Attributes
369
+
370
+ ```html
371
+ <a
372
+ href="/product/{{ product.id }}"
373
+ class="product-link {{ product.inStock ? '' : 'out-of-stock' }}"
374
+ title="{{ product.name }} - ${{ product.price }}">
375
+ {{ product.name }}
376
+ </a>
377
+ ```
378
+
379
+ ## Next Steps
380
+
381
+ - Learn about [Directives](/guide/directives)
382
+ - See [templating examples](/examples/)
383
+ - Explore [component patterns](/guide/components)
package/docs/index.md ADDED
@@ -0,0 +1,126 @@
1
+ ---
2
+ layout: home
3
+
4
+ hero:
5
+ name: LegoJS
6
+ text: Build Reactive Web Components
7
+ tagline: A tiny, zero-dependency JavaScript library for creating reactive Web Components directly in the browser
8
+ image:
9
+ src: /logo.svg
10
+ alt: LegoJS
11
+ actions:
12
+ - theme: brand
13
+ text: Get Started
14
+ link: /guide/getting-started
15
+ - theme: alt
16
+ text: View on GitHub
17
+ link: https://github.com/rayattack/LegoJS
18
+ - theme: alt
19
+ text: Try Examples
20
+ link: /examples/
21
+
22
+ features:
23
+ - icon: 🎯
24
+ title: Mental Model Simplicity
25
+ details: No virtual DOM, no compilation step, no JSX. Just HTML with a few directives and reactive objects.
26
+
27
+ - icon: ⚡
28
+ title: Zero Dependencies
29
+ details: Under 500 lines of code with no external dependencies. The entire library is smaller than most framework router plugins.
30
+
31
+ - icon: 🔄
32
+ title: True Reactivity
33
+ details: Direct object mutation triggers updates. No setters, no actions, no reducers. Just change the data and the DOM updates.
34
+
35
+ - icon: 🧩
36
+ title: Web Components Native
37
+ details: Built on standard Web Components with Shadow DOM. Works anywhere, plays well with existing code.
38
+
39
+ - icon: 📦
40
+ title: Single File Components
41
+ details: Use .lego files with Vite for a modern development experience, or load directly in the browser.
42
+
43
+ - icon: 🎨
44
+ title: Scoped Styles
45
+ details: Shadow DOM encapsulation means your styles never leak. Use the 'self' keyword to target component root.
46
+
47
+ - icon: 🛣️
48
+ title: Built-in Router
49
+ details: Client-side routing included. Define routes, handle parameters, and add middleware without extra packages.
50
+
51
+ - icon: 💪
52
+ title: TypeScript Ready
53
+ details: Full JSDoc annotations for excellent IDE support and optional TypeScript integration.
54
+
55
+ - icon: 🚀
56
+ title: Production Ready
57
+ details: Battle-tested patterns from Vue and React, adapted for pure Web Components. No framework lock-in.
58
+ ---
59
+
60
+ ## Quick Example
61
+
62
+ ```html
63
+ <!-- Define a component -->
64
+ <template b-id="counter-button">
65
+ <style>
66
+ self {
67
+ display: block;
68
+ padding: 1rem;
69
+ }
70
+ button {
71
+ font-size: 1.2rem;
72
+ padding: 0.5rem 1rem;
73
+ }
74
+ </style>
75
+
76
+ <h2>{{ title }}</h2>
77
+ <button @click="count++">
78
+ Clicked {{ count }} times
79
+ </button>
80
+ </template>
81
+
82
+ <!-- Use it -->
83
+ <counter-button b-data="{ title: 'My Counter', count: 0 }"></counter-button>
84
+
85
+ <script src="https://unpkg.com/lego-dom/main.js"></script>
86
+ ```
87
+
88
+ That's it. No build step, no npm, no configuration.
89
+
90
+ ## Why LegoJS?
91
+
92
+ **For small projects**, you get reactive components without the overhead of a full framework.
93
+
94
+ **For large projects**, you get a clear mental model and Web Standards compliance.
95
+
96
+ **For learning**, you can read the entire source code in an afternoon and understand exactly how it works.
97
+
98
+ ## Comparison
99
+
100
+ | Feature | LegoJS | Vue | React |
101
+ |---------|--------|-----|-------|
102
+ | Size | < 17KB | ~33KB | ~40KB |
103
+ | Dependencies | 0 | Many | Many |
104
+ | Build Required | No* | Yes | Yes |
105
+ | Virtual DOM | No | Yes | Yes |
106
+ | Learning Curve | Minimal | Moderate | Moderate |
107
+ | Web Components | Native | Optional | No |
108
+
109
+ \* *Optional with Vite for .lego files*
110
+
111
+ ## Browser Support
112
+
113
+ LegoJS works in all modern browsers that support:
114
+ - Web Components
115
+ - Shadow DOM
116
+ - ES6 Proxy
117
+ - Template literals
118
+
119
+ This includes Chrome 63+, Firefox 63+, Safari 11.1+, and Edge 79+.
120
+
121
+ ## Community
122
+
123
+ - 📖 [Documentation](https://rayattack.github.io/LegoJS/)
124
+ - 💬 [Discussions](https://github.com/rayattack/LegoJS/discussions)
125
+ - 🐛 [Issue Tracker](https://github.com/rayattack/LegoJS/issues)
126
+ - 📦 [npm Package](https://www.npmjs.com/package/lego-dom)
@@ -0,0 +1,38 @@
1
+ <svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="blockGrad" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#FF4B2B" />
5
+ <stop offset="100%" style="stop-color:#FF416C" />
6
+ </linearGradient>
7
+ <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
8
+ <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
9
+ <feOffset dx="2" dy="4" result="offsetblur" />
10
+ <feComponentTransfer>
11
+ <feFuncA type="linear" slope="0.2" />
12
+ </feComponentTransfer>
13
+ <feMerge>
14
+ <feMergeNode />
15
+ <feMergeNode in="SourceGraphic" />
16
+ </feMerge>
17
+ </filter>
18
+ </defs>
19
+
20
+ <g filter="url(#shadow)" transform="translate(40, 40)">
21
+ <path d="M60 80 L90 65 L90 95 L60 110 Z" fill="#D32F2F" />
22
+ <path d="M90 65 L120 80 L120 110 L90 95 Z" fill="#B71C1C" />
23
+ <path d="M60 80 L90 65 L120 80 L90 95 Z" fill="url(#blockGrad)" />
24
+ <circle cx="90" cy="80" r="4" fill="white" fill-opacity="0.3" />
25
+
26
+ <path d="M30 65 L60 50 L60 80 L30 95 Z" fill="#D32F2F" />
27
+ <path d="M60 50 L90 65 L90 95 L60 80 Z" fill="#B71C1C" />
28
+ <path d="M30 65 L60 50 L90 65 L60 80 Z" fill="url(#blockGrad)" />
29
+ <circle cx="60" cy="65" r="4" fill="white" fill-opacity="0.3" />
30
+
31
+ <path d="M30 35 L60 20 L60 50 L30 65 Z" fill="#D32F2F" />
32
+ <path d="M60 20 L90 35 L90 65 L60 50 Z" fill="#B71C1C" />
33
+ <path d="M30 35 L60 20 L90 35 L60 50 Z" fill="url(#blockGrad)" />
34
+ <circle cx="60" cy="35" r="4" fill="white" fill-opacity="0.3" />
35
+ </g>
36
+
37
+ <text x="100" y="180" font-family="Arial, sans-serif" font-weight="900" font-size="24" fill="#333" text-anchor="middle" letter-spacing="1">LEGO.JS</text>
38
+ </svg>
@@ -0,0 +1,71 @@
1
+ # LegoJS SFC and Vite Plugin Example
2
+
3
+ This example demonstrates how to use LegoJS with Single File Components (.lego files) and the Vite plugin.
4
+
5
+ ## Setup
6
+
7
+ 1. Install dependencies:
8
+ ```bash
9
+ npm install
10
+ ```
11
+
12
+ 2. Run the dev server:
13
+ ```bash
14
+ npm run dev
15
+ ```
16
+
17
+ 3. Open your browser to the URL shown (usually `http://localhost:5173`)
18
+
19
+ ## Structure
20
+
21
+ ```
22
+ examples/vite-app/
23
+ ├── src/
24
+ │ ├── components/ # .lego files auto-discovered here
25
+ │ │ ├── sample-component.lego
26
+ │ │ └── greeting-card.lego
27
+ │ └── main.js # Entry point
28
+ ├── index.html # HTML shell
29
+ ├── vite.config.js # Vite configuration with lego plugin
30
+ └── package.json
31
+ ```
32
+
33
+ ## How It Works
34
+
35
+ 1. The Vite plugin scans `src/components/` for `.lego` files
36
+ 2. Each `.lego` file is parsed and transformed into a `Lego.define()` call
37
+ 3. The virtual module `virtual:lego-components` imports all discovered components
38
+ 4. Components are automatically registered and available in your HTML
39
+
40
+ ## Creating Components
41
+
42
+ Create a new `.lego` file in `src/components/`:
43
+
44
+ ```html
45
+ <template>
46
+ <h1>{{ message }}</h1>
47
+ <button @click="count++">{{ count }}</button>
48
+ </template>
49
+
50
+ <script>
51
+ export default {
52
+ message: 'Hello!',
53
+ count: 0
54
+ }
55
+ </script>
56
+
57
+ <style>
58
+ self {
59
+ display: block;
60
+ padding: 1rem;
61
+ }
62
+ </style>
63
+ ```
64
+
65
+ Then use it in your HTML:
66
+
67
+ ```html
68
+ <your-component-name></your-component-name>
69
+ ```
70
+
71
+ The component name is automatically derived from the filename (kebab-case required).
@@ -0,0 +1,45 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>LegoJS Vite Example</title>
7
+ <style>
8
+ body {
9
+ font-family: system-ui, -apple-system, sans-serif;
10
+ max-width: 800px;
11
+ margin: 2rem auto;
12
+ padding: 0 1rem;
13
+ background: #f9fafb;
14
+ }
15
+
16
+ h1 {
17
+ color: #1f2937;
18
+ border-bottom: 3px solid #4f46e5;
19
+ padding-bottom: 0.5rem;
20
+ }
21
+
22
+ .info {
23
+ background: white;
24
+ padding: 1rem;
25
+ border-radius: 0.5rem;
26
+ margin: 1rem 0;
27
+ border-left: 4px solid #10b981;
28
+ }
29
+ </style>
30
+ </head>
31
+ <body>
32
+ <h1>LegoJS + Vite Example</h1>
33
+
34
+ <div class="info">
35
+ <p><strong>✨ These components are auto-discovered from .lego files!</strong></p>
36
+ <p>The Vite plugin automatically finds all .lego files in <code>src/components/</code> and registers them.</p>
37
+ </div>
38
+
39
+ <!-- These components are automatically discovered and hydrated -->
40
+ <sample-component></sample-component>
41
+ <greeting-card></greeting-card>
42
+
43
+ <script type="module" src="/src/main.js"></script>
44
+ </body>
45
+ </html>
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "lego-vite-example",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "vite build",
8
+ "preview": "vite preview"
9
+ },
10
+ "dependencies": {
11
+ "lego-dom": "file:../.."
12
+ },
13
+ "devDependencies": {
14
+ "vite": "^5.0.0"
15
+ }
16
+ }