lego-dom 0.0.8 β†’ 1.0.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 (175) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +49 -432
  3. package/cdn.html +124 -0
  4. package/docs/.vitepress/config.js +43 -5
  5. package/docs/api/directives.md +3 -3
  6. package/docs/api/globals.md +1 -1
  7. package/docs/api/index.md +3 -3
  8. package/docs/api/vite-plugin.md +1 -1
  9. package/docs/contributing/01-welcome.md +36 -0
  10. package/docs/contributing/02-registry.md +99 -0
  11. package/docs/contributing/03-batcher.md +110 -0
  12. package/docs/contributing/04-reactivity.md +87 -0
  13. package/docs/contributing/05-caching.md +59 -0
  14. package/docs/contributing/06-init.md +125 -0
  15. package/docs/contributing/07-observer.md +69 -0
  16. package/docs/contributing/08-snap.md +126 -0
  17. package/docs/contributing/09-diffing.md +69 -0
  18. package/docs/contributing/10-studs.md +76 -0
  19. package/docs/contributing/11-scanner.md +104 -0
  20. package/docs/contributing/12-render.md +116 -0
  21. package/docs/contributing/13-directives.md +225 -0
  22. package/docs/contributing/14-events.md +57 -0
  23. package/docs/contributing/15-router.md +9 -0
  24. package/docs/contributing/16-state.md +48 -0
  25. package/docs/contributing/17-legodom.md +55 -0
  26. package/docs/contributing/index.md +5 -0
  27. package/docs/examples/form.md +2 -2
  28. package/docs/examples/index.md +4 -4
  29. package/docs/examples/routing.md +8 -8
  30. package/docs/examples/sfc-showcase.md +4 -4
  31. package/docs/examples/todo-app.md +3 -3
  32. package/docs/guide/cdn-usage.md +16 -8
  33. package/docs/guide/components.md +34 -16
  34. package/docs/guide/contributing.md +2 -2
  35. package/docs/guide/directives.md +23 -23
  36. package/docs/guide/getting-started.md +41 -16
  37. package/docs/guide/index.md +12 -12
  38. package/docs/guide/lifecycle.md +1 -1
  39. package/docs/guide/quick-start.md +8 -5
  40. package/docs/guide/reactivity.md +30 -9
  41. package/docs/guide/routing.md +189 -289
  42. package/docs/guide/sfc.md +40 -40
  43. package/docs/guide/templating.md +4 -4
  44. package/docs/index.md +48 -14
  45. package/docs/public/logo.svg +17 -38
  46. package/docs/router/basic-routing.md +103 -0
  47. package/docs/router/cold-entry.md +91 -0
  48. package/docs/router/history.md +69 -0
  49. package/docs/router/index.md +73 -0
  50. package/docs/router/resolver.md +74 -0
  51. package/docs/router/surgical-swaps.md +134 -0
  52. package/examples/vite-app/README.md +2 -2
  53. package/examples/vite-app/index.html +9 -13
  54. package/examples/vite-app/package.json +4 -2
  55. package/examples/vite-app/src/app.css +3 -0
  56. package/examples/vite-app/src/app.js +29 -0
  57. package/examples/vite-app/src/components/app-navbar.lego +34 -0
  58. package/examples/vite-app/src/components/customers/customer-details.lego +24 -0
  59. package/examples/vite-app/src/components/customers/customer-orders.lego +21 -0
  60. package/examples/vite-app/src/components/customers/order-list.lego +55 -0
  61. package/examples/vite-app/src/components/greeting-card.lego +26 -26
  62. package/examples/vite-app/src/components/sample-component.lego +58 -58
  63. package/examples/vite-app/src/components/shells/customers-shell.lego +21 -0
  64. package/examples/vite-app/src/components/todo-list.lego +239 -0
  65. package/examples/vite-app/src/components/widgets/user-card.lego +27 -0
  66. package/examples/vite-app/vite.config.js +7 -2
  67. package/lego.js +2 -0
  68. package/main.js +280 -83
  69. package/package.json +8 -3
  70. package/parse-lego.js +17 -8
  71. package/parse-lego.test.js +1 -1
  72. package/{main.test.js β†’ tests/main.test.js} +34 -17
  73. package/tests/parse-lego.test.js +65 -0
  74. package/vite-plugin.js +62 -24
  75. package/docs/.vitepress/dist/404.html +0 -22
  76. package/docs/.vitepress/dist/api/define.html +0 -35
  77. package/docs/.vitepress/dist/api/directives.html +0 -32
  78. package/docs/.vitepress/dist/api/globals.html +0 -27
  79. package/docs/.vitepress/dist/api/index.html +0 -25
  80. package/docs/.vitepress/dist/api/lifecycle.html +0 -38
  81. package/docs/.vitepress/dist/api/route.html +0 -34
  82. package/docs/.vitepress/dist/api/vite-plugin.html +0 -37
  83. package/docs/.vitepress/dist/assets/api_define.md.UA-ygUnQ.js +0 -11
  84. package/docs/.vitepress/dist/assets/api_define.md.UA-ygUnQ.lean.js +0 -1
  85. package/docs/.vitepress/dist/assets/api_directives.md.BV-D251p.js +0 -8
  86. package/docs/.vitepress/dist/assets/api_directives.md.BV-D251p.lean.js +0 -1
  87. package/docs/.vitepress/dist/assets/api_globals.md.DOjt7AV0.js +0 -3
  88. package/docs/.vitepress/dist/assets/api_globals.md.DOjt7AV0.lean.js +0 -1
  89. package/docs/.vitepress/dist/assets/api_index.md.OS6h01ct.js +0 -1
  90. package/docs/.vitepress/dist/assets/api_index.md.OS6h01ct.lean.js +0 -1
  91. package/docs/.vitepress/dist/assets/api_lifecycle.md.Ccm5xw6-.js +0 -14
  92. package/docs/.vitepress/dist/assets/api_lifecycle.md.Ccm5xw6-.lean.js +0 -1
  93. package/docs/.vitepress/dist/assets/api_route.md.CAHf_KNp.js +0 -10
  94. package/docs/.vitepress/dist/assets/api_route.md.CAHf_KNp.lean.js +0 -1
  95. package/docs/.vitepress/dist/assets/api_vite-plugin.md.DNn9VhL5.js +0 -13
  96. package/docs/.vitepress/dist/assets/api_vite-plugin.md.DNn9VhL5.lean.js +0 -1
  97. package/docs/.vitepress/dist/assets/app.BG5s3B0P.js +0 -1
  98. package/docs/.vitepress/dist/assets/chunks/@localSearchIndexroot.DQmuWC2Z.js +0 -1
  99. package/docs/.vitepress/dist/assets/chunks/VPLocalSearchBox.BO-PSxt1.js +0 -9
  100. package/docs/.vitepress/dist/assets/chunks/framework.B7OFBR9X.js +0 -19
  101. package/docs/.vitepress/dist/assets/chunks/theme.DA-iSa9B.js +0 -2
  102. package/docs/.vitepress/dist/assets/examples_form.md.B3stGKbu.js +0 -34
  103. package/docs/.vitepress/dist/assets/examples_form.md.B3stGKbu.lean.js +0 -1
  104. package/docs/.vitepress/dist/assets/examples_index.md.BDEG_D4J.js +0 -30
  105. package/docs/.vitepress/dist/assets/examples_index.md.BDEG_D4J.lean.js +0 -1
  106. package/docs/.vitepress/dist/assets/examples_routing.md.bqZ9DjDK.js +0 -338
  107. package/docs/.vitepress/dist/assets/examples_routing.md.bqZ9DjDK.lean.js +0 -1
  108. package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DLXaUiop.js +0 -13
  109. package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DLXaUiop.lean.js +0 -1
  110. package/docs/.vitepress/dist/assets/examples_todo-app.md.D5RhZoo5.js +0 -297
  111. package/docs/.vitepress/dist/assets/examples_todo-app.md.D5RhZoo5.lean.js +0 -1
  112. package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CAjf03Lr.js +0 -182
  113. package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CAjf03Lr.lean.js +0 -1
  114. package/docs/.vitepress/dist/assets/guide_components.md.BIFWF1Hc.js +0 -174
  115. package/docs/.vitepress/dist/assets/guide_components.md.BIFWF1Hc.lean.js +0 -1
  116. package/docs/.vitepress/dist/assets/guide_contributing.md.BgbUN-Mr.js +0 -1
  117. package/docs/.vitepress/dist/assets/guide_contributing.md.BgbUN-Mr.lean.js +0 -1
  118. package/docs/.vitepress/dist/assets/guide_directives.md.Bi3ynu1d.js +0 -140
  119. package/docs/.vitepress/dist/assets/guide_directives.md.Bi3ynu1d.lean.js +0 -1
  120. package/docs/.vitepress/dist/assets/guide_getting-started.md.2Nr1lp2z.js +0 -107
  121. package/docs/.vitepress/dist/assets/guide_getting-started.md.2Nr1lp2z.lean.js +0 -1
  122. package/docs/.vitepress/dist/assets/guide_index.md.GvZq_Yf2.js +0 -2
  123. package/docs/.vitepress/dist/assets/guide_index.md.GvZq_Yf2.lean.js +0 -1
  124. package/docs/.vitepress/dist/assets/guide_lifecycle.md.B28j1OzS.js +0 -304
  125. package/docs/.vitepress/dist/assets/guide_lifecycle.md.B28j1OzS.lean.js +0 -1
  126. package/docs/.vitepress/dist/assets/guide_quick-start.md.CNk3VGTF.js +0 -33
  127. package/docs/.vitepress/dist/assets/guide_quick-start.md.CNk3VGTF.lean.js +0 -1
  128. package/docs/.vitepress/dist/assets/guide_reactivity.md.CVsaMaPv.js +0 -135
  129. package/docs/.vitepress/dist/assets/guide_reactivity.md.CVsaMaPv.lean.js +0 -1
  130. package/docs/.vitepress/dist/assets/guide_routing.md.DSpDP25o.js +0 -193
  131. package/docs/.vitepress/dist/assets/guide_routing.md.DSpDP25o.lean.js +0 -1
  132. package/docs/.vitepress/dist/assets/guide_sfc.md.CVUP66tS.js +0 -187
  133. package/docs/.vitepress/dist/assets/guide_sfc.md.CVUP66tS.lean.js +0 -1
  134. package/docs/.vitepress/dist/assets/guide_templating.md.BgCGe4aa.js +0 -119
  135. package/docs/.vitepress/dist/assets/guide_templating.md.BgCGe4aa.lean.js +0 -1
  136. package/docs/.vitepress/dist/assets/index.md.xV1taCED.js +0 -23
  137. package/docs/.vitepress/dist/assets/index.md.xV1taCED.lean.js +0 -1
  138. package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  139. package/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  140. package/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  141. package/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  142. package/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  143. package/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  144. package/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  145. package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  146. package/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  147. package/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  148. package/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  149. package/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  150. package/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  151. package/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  152. package/docs/.vitepress/dist/assets/style.eycE2Jhw.css +0 -1
  153. package/docs/.vitepress/dist/examples/form.html +0 -58
  154. package/docs/.vitepress/dist/examples/index.html +0 -368
  155. package/docs/.vitepress/dist/examples/routing.html +0 -362
  156. package/docs/.vitepress/dist/examples/sfc-showcase.html +0 -37
  157. package/docs/.vitepress/dist/examples/todo-app.html +0 -321
  158. package/docs/.vitepress/dist/guide/cdn-usage.html +0 -206
  159. package/docs/.vitepress/dist/guide/components.html +0 -198
  160. package/docs/.vitepress/dist/guide/contributing.html +0 -25
  161. package/docs/.vitepress/dist/guide/directives.html +0 -164
  162. package/docs/.vitepress/dist/guide/getting-started.html +0 -131
  163. package/docs/.vitepress/dist/guide/index.html +0 -26
  164. package/docs/.vitepress/dist/guide/lifecycle.html +0 -328
  165. package/docs/.vitepress/dist/guide/quick-start.html +0 -57
  166. package/docs/.vitepress/dist/guide/reactivity.html +0 -159
  167. package/docs/.vitepress/dist/guide/routing.html +0 -217
  168. package/docs/.vitepress/dist/guide/sfc.html +0 -211
  169. package/docs/.vitepress/dist/guide/templating.html +0 -143
  170. package/docs/.vitepress/dist/hashmap.json +0 -1
  171. package/docs/.vitepress/dist/index.html +0 -47
  172. package/docs/.vitepress/dist/logo.svg +0 -38
  173. package/docs/.vitepress/dist/vp-icons.css +0 -1
  174. package/examples/vite-app/src/main.js +0 -11
  175. package/examples.js +0 -99
package/CHANGELOG.md ADDED
@@ -0,0 +1,44 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [1.0.0] - 2026-01-10
6
+
7
+ **The Launch Release!** πŸš€
8
+ LegoDOM moves out of beta with a finalized API, robust routing, and a hybrid rendering engine.
9
+
10
+ ### 🌟 Major features
11
+
12
+ - **Surgical Routing:** Introduced a groundbreaking `b-target` attribute that allows any link to update any part of the page without a full reload.
13
+ - **Smart History:** The router now tracks surgical updates in `history.state`, correctly restoring "fragment" states when using the Back/Forward buttons.
14
+ - **Persistent Layouts:** Support for "Holy Grail" layouts where sidebars never reload or lose state (scroll position, inputs) while main content changes.
15
+ - **Hybrid Rendering Engine:**
16
+ - **Light DOM Support:** The engine now hydrates `{{mustaches}}` in `index.html` and Light DOM slots, not just inside Shadow Roots.
17
+ - **Global Reactivity:** Components now automatically broadcast global state changes (like URL params) to all active subscribers.
18
+ - **Optimized Updates:** A dependency tracking system ensures only components that *use* global state are re-rendered.
19
+ - **Developer Experience (DX):**
20
+ - **Automatic Injection:** `$route` and `$go` are now injected into every component's script scope (`this.$route`, `this.$go`), removing the need for `Lego.globals.xxx`.
21
+ - **Cleaner Templates:** Template expressions now support `$route` directly (`{{ $route.params.id }}`) without `global.` prefix.
22
+ - **HMR 2.0:** The Vite plugin now correctly handles adding/deleting `.lego` files and performs smarter hot updates.
23
+
24
+ ### ⚑ Improvements
25
+
26
+ - **Router:**
27
+ - Exposed `$go(path, ...targets).get()` for programmatic surgical navigation.
28
+ - Fixed `TypeError` where `$go` was not found in component scopes.
29
+ - Support for multiple URL parameters (e.g., `/customers/:id/orders/:orderId`).
30
+ - Defaults `b-link` to `true` (always push history) unless explicitly set to `false`.
31
+ - **Core:**
32
+ - `Lego.init()` is now required to start the engine, allowing for explicit control over startup timing.
33
+ - `e.composedPath()` is used for event delegation, allowing links inside Shadow DOM to trigger the global router.
34
+ - Fixed `b-sync` losing reactivity inside `b-for` loops.
35
+ - Fixed hydration of attributes like `href="/user/{{id}}"`.
36
+ - **Docs:**
37
+ - Complete overhaul of Routing guide with "Surgical Swaps", "Deep Linking", and "Self-Healing" patterns.
38
+ - Clarified component naming conventions (Filename for Vite vs. `b-id` for CDN).
39
+
40
+ ### πŸ› Bug Fixes
41
+
42
+ - Fixed "Literal Mustaches" appearing in `href` and text content on initial load.
43
+ - Fixed Deep Linking where hitting Refresh on a sub-route would render an empty shell (addressed via Self-Healing pattern).
44
+ - Fixed an issue where `Lego.globals` changes triggered a full re-render of unrelated components.
package/README.md CHANGED
@@ -1,466 +1,83 @@
1
- # LegoJS
1
+ # Lego 🧱
2
2
 
3
- LegoJS is a tiny, zero-dependency JavaScript library for building reactive Web Components directly in the browser.
3
+ **The tiny, zero-dependency library for building reactive Web Components.**
4
4
 
5
- The goal of LegoJS is **mental model simplicity**:
5
+ Lego embraces the web platform. It turns standard HTML `<template>` tags into reactive, encapsulated custom elements with zero build steps required.
6
6
 
7
- * No virtual DOM
8
- * No compilation step required
9
- * No JSX
10
- * No framework-specific syntax to learn
11
-
12
- You write **HTML**, add a few **directives**, and LegoJS takes care of reactivity and updates.
13
-
14
- This README is intentionally designed so that a developer can understand **everything they need** about LegoJS by reading this file alone.
15
-
16
- ---
17
-
18
- ## Installation
19
-
20
- The package name on npm is **`lego-dom`** (the name `legojs` was already taken).
21
-
22
- ```bash
23
- npm install lego-dom
24
- ```
25
-
26
- Or include it directly in the browser:
27
-
28
- ```html
29
- <script src="node_modules/lego-dom/main.js"></script>
30
- ```
31
-
32
- Once loaded, `Lego` is available globally.
33
-
34
- ---
35
-
36
- ## The Mental Model
37
-
38
- Think of LegoJS like real Lego blocks:
39
-
40
- * **Templates** define how a block looks
41
- * **Studs** define the data attached to a block
42
- * **Directives** snap data to the DOM
43
- * **Changes to data automatically update the DOM**
44
-
45
- There is no mounting, diffing, or reconciliation engine.
46
-
47
- You change JavaScript objects β†’ LegoJS updates the DOM.
48
-
49
- ---
50
-
51
- ## Defining a Component (Block)
52
-
53
- A component is defined using a standard HTML `<template>` with a `b-id`.
54
-
55
- ```html
56
- <template b-id="hello-card">
57
- <style>
58
- self {
59
- display: block;
60
- padding: 1rem;
61
- border: 1px solid #ccc;
62
- }
63
- </style>
64
-
65
- <h2>Hello {{ name }}</h2>
66
- <button @click="count++">Clicked {{ count }} times</button>
67
- </template>
68
- ```
69
-
70
- Use the component in HTML:
71
-
72
- ```html
73
- <hello-card b-data="{ name: 'Ahmed', count: 0 }"></hello-card>
74
- ```
75
-
76
- ---
77
-
78
- ## Reactive State (`studs`)
79
-
80
- Each component has a reactive state object internally called **studs**.
81
-
82
- * Defined via `b-data` or component logic
83
- * Implemented using JavaScript `Proxy`
84
- * Any mutation automatically schedules a re-render
85
-
86
- ```html
87
- <button @click="count++"></button>
88
- ```
89
-
90
- No setters. No actions. No reducers.
91
-
92
- Just mutate data.
93
-
94
- ---
95
-
96
- ## Templating (`{{ }}`)
97
-
98
- Text interpolation works in:
99
-
100
- * Text nodes
101
- * Attributes
102
- * Class names
103
-
104
- ```html
105
- <p>Hello {{ user.name }}</p>
106
- <img src="/avatars/{{ user.id }}.png">
107
- ```
108
-
109
- Expressions are plain JavaScript.
110
-
111
- ---
112
-
113
- ## Event Handling (`@event`)
114
-
115
- Use `@` followed by any DOM event.
116
-
117
- ```html
118
- <button @click="submit()">Submit</button>
119
- ```
120
-
121
- The expression runs in the component’s state scope.
122
-
123
- You also have access to:
124
-
125
- * `event` – the native DOM event
126
- * `$emit(name, detail)` – dispatch custom events
127
- * `$element` – the host custom element
128
-
129
- ---
130
-
131
- ## Conditional Rendering (`b-if`)
132
-
133
- ```html
134
- <p b-if="isLoggedIn">Welcome back</p>
135
- ```
136
-
137
- When the expression is falsy, the element is hidden via `display: none`.
138
-
139
- ---
140
-
141
- ## Lists (`b-for`)
142
-
143
- Render lists using `b-for`:
144
-
145
- ```html
146
- <ul>
147
- <li b-for="todo in todos">
148
- <input type="checkbox" b-sync="todo.done">
149
- <span class="{{ todo.done ? 'done' : '' }}">{{ todo.text }}</span>
150
- </li>
151
- </ul>
152
- ```
153
-
154
- * DOM nodes are reused
155
- * Items are tracked internally
156
- * Updates are efficient without a virtual DOM
157
-
158
- ---
159
-
160
- ## Two-Way Binding (`b-sync`)
161
-
162
- `b-sync` keeps inputs and state in sync.
163
-
164
- ```html
165
- <input b-sync="username">
166
- <input type="checkbox" b-sync="settings.enabled">
167
- ```
168
-
169
- Works with:
170
-
171
- * text inputs
172
- * checkboxes
173
- * nested objects
174
- * items inside `b-for`
175
-
176
- ---
177
-
178
- ## Styling and Shadow DOM
179
-
180
- Every component uses **Shadow DOM** automatically.
181
-
182
- Inside `<style>` blocks:
183
-
184
- * Use `self` to target the component root
185
- * `self` is converted to `:host`
186
-
187
- ```css
188
- self {
189
- display: block;
190
- }
191
- ```
192
-
193
- Styles never leak in or out.
194
-
195
- ---
196
-
197
- ## Lifecycle Hooks
198
-
199
- Define lifecycle methods directly on the component state:
200
-
201
- ```js
202
- {
203
- mounted() {
204
- console.log('Component attached');
205
- },
206
- updated() {
207
- console.log('State changed');
208
- },
209
- unmounted() {
210
- console.log('Component removed');
211
- }
212
- }
213
- ```
7
+ [**Explore the Docs**](https://rayattack.github.io/legodom/) | [**Examples**](https://rayattack.github.io/legodom/examples/) | [**GitHub**](https://github.com/rayattack/legodom)
214
8
 
215
9
  ---
216
10
 
217
- ## Custom Events (`$emit`)
218
-
219
- Child components communicate upward using events.
11
+ ## Why Lego?
220
12
 
221
- ```html
222
- <button @click="$emit('save', data)">Save</button>
223
- ```
224
-
225
- Events:
226
-
227
- * bubble
228
- * cross Shadow DOM boundaries
229
- * are standard `CustomEvent`s
13
+ - ⚑ **Extremely Fast** – No virtual DOM. No reconciliation. Direct DOM updates.
14
+ - πŸ“¦ **Zero Dependencies** – Weighs less than 4kb gzipped.
15
+ - πŸ› οΈ **No Build Step** – Works directly in the browser with standard `<script>` tags.
16
+ - 🧩 **Native Web Components** – Real Custom Elements, real Shadow DOM.
17
+ - 🌐 **Built-in Routing** – Lego Router included for client-side routing.
18
+ - πŸ“ **Familiar Mentals** – Plain JavaScript objects for state, plain HTML for templates.
230
19
 
231
20
  ---
232
21
 
233
- ## Accessing Ancestors (`$ancestors`)
234
-
235
- Read state from the nearest ancestor component:
236
-
237
- ```html
238
- <p>{{ $ancestors('app-shell').user.name }}</p>
239
- ```
240
-
241
- This is intended for **reading**, not mutation.
242
-
243
- ---
244
-
245
- ## Shared State (`$registry`)
246
-
247
- Components defined via `Lego.define` get a shared singleton state.
248
-
249
- ```js
250
- $registry('settings').theme
251
- ```
252
-
253
- Useful for global configuration or app-wide state.
254
-
255
- ---
256
-
257
- ## Router
258
-
259
- LegoJS includes a minimal client-side router.
260
-
261
- Add a router outlet:
262
-
263
- ```html
264
- <lego-router></lego-router>
265
- ```
266
-
267
- Define routes:
268
-
269
- ```js
270
- Lego.route('/', 'home-page');
271
- Lego.route('/user/:id', 'user-page');
272
- ```
273
-
274
- Access route params:
22
+ ## Quick Start (No Build Required)
275
23
 
276
24
  ```html
277
- <p>User ID: {{ global.params.id }}</p>
278
- ```
25
+ <!DOCTYPE html>
26
+ <html>
27
+ <body>
28
+ <hello-world></hello-world>
279
29
 
280
- Navigation:
30
+ <template b-id="hello-world">
31
+ <style>
32
+ h1 { color: #ffca28; font-family: sans-serif; }
33
+ </style>
34
+ <h1>Hello, {{ name }}!</h1>
35
+ <button @click="toggle()">Toggle Name</button>
36
+ </template>
281
37
 
282
- ```html
283
- <a href="/dashboard" b-link>Dashboard</a>
38
+ <script src="https://unpkg.com/lego-dom/main.js"></script>
39
+ <script>
40
+ document.querySelector('hello-world').state = {
41
+ name: 'World',
42
+ toggle() {
43
+ this.name = this.name === 'World' ? 'Lego' : 'World';
44
+ }
45
+ };
46
+ </script>
47
+ </body>
48
+ </html>
284
49
  ```
285
50
 
286
51
  ---
287
52
 
288
- ## Programmatic Navigation
289
-
290
- ```js
291
- history.pushState({}, '', '/success');
292
- window.dispatchEvent(new PopStateEvent('popstate'));
293
- ```
294
-
295
- ---
296
-
297
- ## Defining Components in JavaScript
298
-
299
- You can also define components programmatically:
300
-
301
- ```js
302
- Lego.define(
303
- 'counter-box',
304
- `
305
- <style>self { display:block }</style>
306
- <button @click="count++">{{ count }}</button>
307
- `,
308
- { count: 0 }
309
- );
310
- ```
311
-
312
- ---
313
-
314
- ## Initialization
315
-
316
- LegoJS initializes automatically on `DOMContentLoaded`.
317
-
318
- You usually do **not** need to call anything manually.
319
-
320
- ---
321
-
322
- ## Design Philosophy
323
-
324
- LegoJS is intentionally small and opinionated:
325
-
326
- * The DOM is the source of truth
327
- * JavaScript objects are the state
328
- * HTML stays HTML
329
- * Complexity is avoided unless absolutely necessary
330
-
331
- If you can explain your UI with plain objects and markup, LegoJS will feel natural.
332
-
333
- ---
334
-
335
- ## Single File Components (SFC)
53
+ ## Also Supports Modern Toolchains
336
54
 
337
- LegoJS supports **Single File Components** using `.lego` files when using a build tool like Vite.
338
-
339
- ### .lego File Format
340
-
341
- A `.lego` file contains three optional sections:
55
+ Lego includes a **Vite plugin** for developers who prefer **Single File Components (.lego)**:
342
56
 
343
57
  ```html
58
+ <!-- user-card.lego -->
344
59
  <template>
345
- <!-- Your HTML markup with directives -->
346
- <h1>{{ title }}</h1>
347
- <button @click="count++">{{ count }}</button>
60
+ <h1>{{ name }}</h1>
348
61
  </template>
349
62
 
350
- <script>
351
- export default {
352
- // Your component logic/state
353
- title: 'Hello',
354
- count: 0
355
- }
356
- </script>
357
-
358
63
  <style>
359
- /* Scoped CSS using self keyword */
360
- self {
361
- display: block;
362
- padding: 1rem;
363
- }
64
+ self { display: block; padding: 20px; }
364
65
  </style>
365
- ```
366
-
367
- The component name is automatically derived from the filename (e.g., `sample-component.lego` β†’ `<sample-component>`).
368
-
369
- ---
370
-
371
- ## Vite Plugin Setup
372
-
373
- ### Installation
374
-
375
- ```bash
376
- npm install lego-dom vite
377
- ```
378
-
379
- ### Configuration
380
-
381
- Create `vite.config.js`:
382
-
383
- ```js
384
- import { defineConfig } from 'vite';
385
- import legoPlugin from 'lego-dom/vite-plugin';
386
-
387
- export default defineConfig({
388
- plugins: [
389
- legoPlugin({
390
- componentsDir: './src/components', // Where to look for .lego files
391
- include: ['**/*.lego'] // Glob patterns to match
392
- })
393
- ]
394
- });
395
- ```
396
-
397
- ### Usage
398
-
399
- Create your components in `.lego` files:
400
-
401
- ```
402
- src/
403
- components/
404
- my-button.lego
405
- user-card.lego
406
- main.js
407
- index.html
408
- ```
409
-
410
- In your `main.js`:
411
-
412
- ```js
413
- import { Lego } from 'lego-dom/main.js';
414
- import registerComponents from 'virtual:lego-components';
415
-
416
- registerComponents();
417
- ```
418
-
419
- In your HTML:
420
66
 
421
- ```html
422
- <my-button></my-button>
423
- <user-card></user-card>
67
+ <script>
68
+ export default { name: 'John Doe' }
69
+ </script>
424
70
  ```
425
71
 
426
- **Auto-discovery**: The Vite plugin automatically finds all `.lego` files and registers them with LegoJS!
427
-
428
72
  ---
429
73
 
430
- ## Two Usage Modes
431
-
432
- LegoJS works in **two modes**:
433
-
434
- ### 1. Without Build Tooling
435
-
436
- Include `main.js` directly and use `<template b-id>` or `Lego.define()`:
437
-
438
- ```html
439
- <script src="node_modules/lego-dom/main.js"></script>
440
- <template b-id="my-component">
441
- <h1>Hello</h1>
442
- </template>
443
- ```
444
-
445
- ### 2. With Vite (SFC)
446
-
447
- Use `.lego` files that are auto-discovered and compiled:
448
-
449
- ```bash
450
- npm run dev
451
- ```
452
-
453
- Both modes use the same LegoJS runtime and support all the same features!
454
-
455
- ---
74
+ ## πŸ”— Links
456
75
 
457
- ## Summary
76
+ - πŸ“– [Full Documentation](https://rayattack.github.io/legodom/)
77
+ - πŸš€ [Quick Start Guide](https://rayattack.github.io/legodom/guide/quick-start)
78
+ - πŸ”Œ [Vite Plugin Setup](https://rayattack.github.io/legodom/api/vite-plugin)
79
+ - πŸ§ͺ [Example Showcase](https://rayattack.github.io/legodom/examples/)
458
80
 
459
- * Install with `npm install lego-dom`
460
- * Define components with `<template b-id>`
461
- * Use `b-data` for state
462
- * Use `{{ }}` for binding
463
- * Use `@event` for logic
464
- * Use `b-if`, `b-for`, and `b-sync` for structure
81
+ ## License
465
82
 
466
- That’s it.
83
+ MIT Β© [Tersoo Ortserga](https://github.com/rayattack)
package/cdn.html ADDED
@@ -0,0 +1,124 @@
1
+ <html lang="en">
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Lego Test</title>
7
+ <script src="./main.js"></script>
8
+ </head>
9
+
10
+ <body @todo-added="() => {console.log('Todo added!')}">
11
+ <template b-id="todo-list" b-data="{
12
+ title: 'My Todo List',
13
+ items: [],
14
+ newItem: '',
15
+ mounted() {
16
+ console.log('Todo list mounted!');
17
+ }
18
+ }">
19
+ <style>
20
+ :host {
21
+ display: block;
22
+ font-family: system-ui, sans-serif;
23
+ padding: 20px;
24
+ }
25
+
26
+ .done {
27
+ text-decoration: line-through;
28
+ color: #888;
29
+ }
30
+
31
+ .input {
32
+ padding: .4em;
33
+ border: 1px solid #ccc;
34
+ border-radius: 0.1em;
35
+ }
36
+
37
+ .item-row {
38
+ margin-bottom: 8px;
39
+ display: flex;
40
+ align-items: center;
41
+ gap: 10px;
42
+ }
43
+
44
+ button {
45
+ cursor: pointer;
46
+ border: none;
47
+ padding: 5px 10px;
48
+ border-radius: 0px;
49
+ background-color: #404;
50
+ color: #fff;
51
+ }
52
+
53
+ h3 {
54
+ color: #318d8d;
55
+ margin-top: 0;
56
+ }
57
+ </style>
58
+
59
+ <h3>{{title}}</h3>
60
+ <p>{{ items.filter(t => !t.done).length }} of {{ items.length }} items remaining</p>
61
+ <div style="margin-bottom: 20px;">
62
+ <input b-sync="newItem" placeholder="Add task..." class="input">
63
+ <button @click="() => {
64
+ if(!newItem.trim()) return;
65
+ items.push({text: `${newItem} - ${items.length + 1}`, done: false});
66
+ newItem = '';
67
+ $emit('todo-added', { item: newItem });
68
+ }">Add</button>
69
+ </div>
70
+
71
+ <div b-for="todo in items">
72
+ <div class="item-row {{todo.done ? 'done' : ''}}">
73
+ <input type="checkbox" b-sync="todo.done">
74
+ <span>{{todo.text}}</span>
75
+ </div>
76
+ </div>
77
+ </template>
78
+
79
+ <template b-id="user-card" b-data="{
80
+ name: 'Anonymous',
81
+ bio: 'No bio provided'
82
+ }">
83
+ <style>
84
+ :host {
85
+ display: block;
86
+ font-family: system-ui, sans-serif;
87
+ padding: 20px;
88
+ border: 1px solid #ccc;
89
+ border-radius: 8px;
90
+ margin-bottom: 20px;
91
+ }
92
+
93
+ h3 {
94
+ color: #62318d;
95
+ margin-top: 0;
96
+ }
97
+ </style>
98
+
99
+ <h3>{{name}}</h3>
100
+ <p>{{bio}}</p>
101
+ <slot></slot>
102
+ </template>
103
+
104
+ <!-- Using defaults -->
105
+ <user-card>
106
+ <p>This user uses default data from the template.</p>
107
+ </user-card>
108
+
109
+ <!-- Overriding defaults -->
110
+ <user-card b-data="{
111
+ name: 'John Doe',
112
+ bio: 'Software Engineer'
113
+ }">
114
+ <p>This user overrides the defaults.</p>
115
+
116
+ <todo-list b-data="{
117
+ title: 'Work Tasks',
118
+ items: [{text: 'Implement template defaults', done: true}]
119
+ }">
120
+ </todo-list>
121
+ </user-card>
122
+ </body>
123
+
124
+ </html>