lego-dom 0.0.4 → 0.0.7

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 (3) hide show
  1. package/README.md +344 -0
  2. package/package.json +3 -4
  3. package/about.md +0 -523
package/README.md ADDED
@@ -0,0 +1,344 @@
1
+ # LegoJS
2
+
3
+ LegoJS is a tiny, zero-dependency JavaScript library for building reactive Web Components directly in the browser.
4
+
5
+ The goal of LegoJS is **mental model simplicity**:
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
+ ```
214
+
215
+ ---
216
+
217
+ ## Custom Events (`$emit`)
218
+
219
+ Child components communicate upward using events.
220
+
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
230
+
231
+ ---
232
+
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:
275
+
276
+ ```html
277
+ <p>User ID: {{ global.params.id }}</p>
278
+ ```
279
+
280
+ Navigation:
281
+
282
+ ```html
283
+ <a href="/dashboard" b-link>Dashboard</a>
284
+ ```
285
+
286
+ ---
287
+
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
+ ## Summary
336
+
337
+ * Install with `npm install lego-dom`
338
+ * Define components with `<template b-id>`
339
+ * Use `b-data` for state
340
+ * Use `{{ }}` for binding
341
+ * Use `@event` for logic
342
+ * Use `b-if`, `b-for`, and `b-sync` for structure
343
+
344
+ That’s it.
package/package.json CHANGED
@@ -1,17 +1,16 @@
1
1
  {
2
2
  "name": "lego-dom",
3
- "version": "0.0.4",
3
+ "version": "0.0.7",
4
4
  "description": "A feature-rich web components + SFC frontend framework",
5
5
  "main": "main.js",
6
6
  "type": "module",
7
7
  "keywords": ["framework", "sfc", "components", "lego", "legokit"],
8
- "author": "Tersoo <ortserga@gmail.com>",
8
+ "author": "",
9
9
  "scripts": {
10
10
  "test": "vitest run"
11
11
  },
12
12
  "devDependencies": {
13
13
  "vitest": "^1.0.0",
14
14
  "jsdom": "^22.0.0"
15
- },
16
- "license": "MIT"
15
+ }
17
16
  }
package/about.md DELETED
@@ -1,523 +0,0 @@
1
- # Lego JS Library
2
-
3
- Lego JS is a surgical, zero-dependency reactive library for building native Web Components. It skips the virtual DOM overhead, leveraging Proxies and Shadow DOM to provide a lightweight (<5KB) alternative to the heavy-duty framework status quo.
4
-
5
- ## 🏗 Core Concepts
6
-
7
- ### 1. Reactive State (`studs`)
8
-
9
- Lego components use a reactive state object called `studs`. State mutations trigger efficient, batched DOM updates via `requestAnimationFrame`—minimizing reflows without a complex reconciliation engine.
10
-
11
- ### 2. Shadow DOM Encapsulation
12
-
13
- Styles and logic are scoped by default. Use the `self` selector inside a component's `<style>` tag to target the host element without worrying about CSS leakage or global collisions.
14
-
15
- ### 3. Directives (`b-`)
16
-
17
- Native-feeling attributes (`b-if`, `b-for`, `b-sync`) bridge your data to the DOM. No JSX, no compilation required for core features—just standard HTML.
18
-
19
- ## 🚀 Quickstart
20
-
21
- ### 📦 Installation
22
-
23
- Drop the script and start building. No build step, no `npm install` fatigue.
24
-
25
- ```
26
- <script src="path/to/main.js"></script>
27
-
28
- ```
29
-
30
- ### 🛠 Creating your first Component
31
-
32
- Define logic and layout in a standard `<template>`.
33
-
34
- ```
35
- <!-- Define -->
36
- <template b-id="greeting-card">
37
- <style>
38
- self { display: block; padding: 20px; border-radius: 8px; background: #f0f4f8; }
39
- </style>
40
-
41
- <h2>Hello, {{ name }}!</h2>
42
- <button @click="showBio = !showBio">Toggle Bio</button>
43
- <p b-if="showBio">{{ bio }}</p>
44
- </template>
45
-
46
- <!-- Execute -->
47
- <greeting-card b-data="{ name: 'Alex', bio: 'Dev', showBio: false }"></greeting-card>
48
-
49
- ```
50
-
51
- ## 📖 Directives Deep Dive
52
-
53
- Directive
54
-
55
- Type
56
-
57
- Description
58
-
59
- Example
60
-
61
- `b-id`
62
-
63
- Definition
64
-
65
- Registers the custom element tag name.
66
-
67
- `<template b-id="my-tag">`
68
-
69
- `b-data`
70
-
71
- Initialization
72
-
73
- Sets the initial reactive state.
74
-
75
- `<my-tag b-data="{ count: 0 }">`
76
-
77
- `b-sync`
78
-
79
- Two-way
80
-
81
- Bi-directional binding for form inputs.
82
-
83
- `<input b-sync="query">`
84
-
85
- `b-for`
86
-
87
- Structural
88
-
89
- High-performance array looping.
90
-
91
- `<li b-for="u in users">{{ u.name }}</li>`
92
-
93
- `b-if`
94
-
95
- Structural
96
-
97
- Toggles presence based on truthiness.
98
-
99
- `<div b-if="isAdmin">Admin</div>`
100
-
101
- `b-text`
102
-
103
- Binding
104
-
105
- Escaped text binding (one-way).
106
-
107
- `<span b-text="title"></span>`
108
-
109
- `@event`
110
-
111
- Event
112
-
113
- Standard DOM event listeners.
114
-
115
- `<button @click="run()">`
116
-
117
- ## 📝 Advanced Example: Todo List
118
-
119
- Demonstrating `b-for`, event handling, and two-way binding in a single block.
120
-
121
- ```
122
- <template b-id="todo-app">
123
- <style>
124
- .done { text-decoration: line-through; opacity: 0.6; }
125
- ul { list-style: none; padding: 0; }
126
- </style>
127
-
128
- <h3>Tasks ({{ tasks.filter(t => !t.done).length }} left)</h3>
129
-
130
- <input b-sync="newTask" placeholder="Add task...">
131
- <button @click="tasks.push({text: newTask, done: false}); newTask=''">Add</button>
132
-
133
- <ul>
134
- <li b-for="task in tasks">
135
- <input type="checkbox" b-sync="task.done">
136
- <span class="{{ task.done ? 'done' : '' }}">{{ task.text }}</span>
137
- </li>
138
- </ul>
139
- </template>
140
-
141
- <script>
142
- export default {
143
- tasks: [{ text: 'Native Components', done: true }, { text: 'Profit', done: false }],
144
- newTask: ''
145
- }
146
- </script>
147
-
148
- ```
149
-
150
- ## 🏗 Tooling & Ecosystem
151
-
152
-
153
- # 📦 Lego Single File Components (.lego)
154
-
155
- Single File Components (SFCs) are the professional standard for building with Lego JS. They allow you to co-locate your markup, scoped CSS, and reactive logic in a single `.lego` file, providing a clean separation of concerns without the mental overhead of switching between multiple files.
156
-
157
- ## 🏗 Anatomy of a .lego File
158
-
159
- A `.lego` file is composed of three top-level blocks: `<template>`, `<style>`, and `<script>`.
160
-
161
- ```
162
- <!-- user-profile.lego -->
163
- <template>
164
- <div class="profile-card">
165
- <img src="{{ avatar }}" alt="{{ name }}">
166
- <h2>{{ name }}</h2>
167
- <p>{{ bio }}</p>
168
- <button @click="poke">Poke {{ name }}</button>
169
- </div>
170
- </template>
171
-
172
- <style>
173
- self {
174
- display: block;
175
- border: 1px solid #ddd;
176
- border-radius: 8px;
177
- padding: 1rem;
178
- text-align: center;
179
- }
180
- img {
181
- width: 80px;
182
- height: 80px;
183
- border-radius: 50%;
184
- }
185
- h2 { color: #333; }
186
- </style>
187
-
188
- <script>
189
- export default {
190
- // Initial data state
191
- avatar: 'default.png',
192
- name: 'Anonymous',
193
- bio: 'No bio provided.',
194
-
195
- // Logic methods
196
- poke() {
197
- console.log(`${this.name} was poked!`);
198
- this.$emit('poked', { name: this.name });
199
- },
200
-
201
- // Lifecycle hooks
202
- mounted() {
203
- console.log('Profile component is now in the DOM');
204
- }
205
- }
206
- </script>
207
-
208
- ```
209
-
210
- ## 🎨 Scoped Styling
211
-
212
- Styles defined inside a `.lego` file are automatically scoped to that component using the **Shadow DOM**.
213
-
214
- - **The `self` selector**: Use `self` to target the host element of the component itself (the custom tag). In the final build, this is converted to the `:host` CSS selector.
215
-
216
- - **No Leakage**: Styles defined here will not leak out to the parent page, and global styles (except CSS variables) will not leak into the component.
217
-
218
-
219
- ## ⚙️ Component Logic (`export default`)
220
-
221
- The `<script>` block must `export default` a plain JavaScript object. This object defines the component's state and behavior.
222
-
223
- ### 1. Reactive Data
224
-
225
- Any property defined in the exported object becomes part of the reactive `data` proxy. When you change `this.username = 'NewName'`, the template updates automatically.
226
-
227
- ### 2. Lifecycle Hooks
228
-
229
- Lego JS provides specific hooks to manage the component's existence:
230
-
231
- Hook
232
-
233
- Description
234
-
235
- `mounted()`
236
-
237
- Called after the component is attached to the DOM and its shadow root is initialized.
238
-
239
- `updated()`
240
-
241
- Called after the state changes and the DOM has been patched via the batcher.
242
-
243
- `unmounted()`
244
-
245
- Called just before the component is removed from the DOM. Use for cleanup (e.g., clearing timers).
246
-
247
- ## ✨ Magic Helpers ($)
248
-
249
- Lego JS provides several "magic" variables available directly in your templates and event handlers to speed up development.
250
-
251
- ### `$element`
252
-
253
- Refers to the host custom element itself (the root of the component).
254
-
255
- ### `$refs`
256
-
257
- Provides quick access to DOM elements within the component's Shadow DOM that have a `ref` attribute.
258
-
259
- ### `$emit(eventName, detail)`
260
-
261
- A shorthand for dispatching custom events. By default, these events have `bubbles: true` and `composed: true`, allowing them to pass through multiple levels of Shadow DOM.
262
-
263
- ### `$ancestors(id)`
264
-
265
- Searches up the DOM tree for the nearest component matching the provided tag name or `b-id`.
266
-
267
- ### `$event` and `$self`
268
-
269
- - `$event`: The native DOM event object.
270
-
271
- - `$self`: The specific element that triggered the event (alias for `event.target`).
272
-
273
-
274
- ## 📡 The "One Way" Pattern (Data Flow)
275
-
276
- While Lego JS allows deep tree access, the **only** recommended way to handle state updates in large apps is **Data Down, Events Up**. This prevents "mutant state" where you don't know which child changed a value.
277
-
278
- ### ❌ The "Bad" Way (Direct Mutation)
279
-
280
- Avoid having children directly change an ancestor's data. It makes debugging impossible.
281
-
282
- ```
283
- <!-- child.lego: DON'T DO THIS -->
284
- <button @click="$ancestors('app-shell').user.age++">Update Age</button>
285
-
286
- ```
287
-
288
- ### ✅ The "Lego" Way (Generic Update Pattern)
289
-
290
- If you have many fields, you don't need unique event handlers for each. Use a single generic update event.
291
-
292
- 1. **Child** sends the field name and the new value:
293
-
294
- ```
295
- <!-- settings-child.lego -->
296
- <input type="text"
297
- value="{{ $ancestors('app-shell').user.name }}"
298
- @input="$emit('update-field', { key: 'name', value: $self.value })">
299
-
300
- <input type="number"
301
- value="{{ $ancestors('app-shell').user.age }}"
302
- @input="$emit('update-field', { key: 'age', value: $self.value })">
303
-
304
- ```
305
-
306
- 2. **Ancestor** handles all updates in one function:
307
-
308
- ```
309
- <!-- grand-parent.lego -->
310
- <template>
311
- <div @update-field="handleFieldUpdate">
312
- <settings-child></settings-child>
313
- </div>
314
- </template>
315
-
316
- <script>
317
- export default {
318
- user: { name: 'John', age: 30 },
319
- handleFieldUpdate(event) {
320
- const { key, value } = event.detail;
321
- // One place to validate everything
322
- if (this.user.hasOwnProperty(key)) {
323
- this.user[key] = value;
324
- }
325
- }
326
- }
327
- </script>
328
-
329
- ```
330
-
331
-
332
- ## 🚀 The Build Process (Vite)
333
-
334
- To use `.lego` files, you must use the `Lego.vitePlugin()`. This plugin transforms your HTML-like file into a standard JavaScript module that registers the component with the `Lego.define` API.
335
-
336
- ### Configuration
337
-
338
- In your `vite.config.js`:
339
-
340
- ```
341
- import { defineConfig } from 'vite';
342
- import { Lego } from './path/to/lego.js';
343
-
344
- export default defineConfig({
345
- plugins: [Lego.vitePlugin()]
346
- });
347
-
348
- ```
349
-
350
- ## 💡 Best Practices
351
-
352
- 1. **Naming**: Use multi-word names for components to avoid collisions.
353
-
354
- 2. **Read-Only Ancestors**: Use `$ancestors()` primarily for **reading** values.
355
-
356
- 3. **Intent-based Events**: For complex logic (e.g., `submit-order`), use a specific event. For simple data syncing, use a generic `update-field` event.
357
-
358
-
359
-
360
- # 🛣 Lego JS Routing Guide
361
-
362
- The Lego JS router is a lightweight client-side routing solution that leverages the browser's History API. It allows you to build Single Page Applications (SPAs) by mapping URL paths to specific Web Components (Blocks).
363
-
364
- ## 🧩 The Router Viewport
365
-
366
- To use routing, you must place the `<lego-router>` element in your HTML. This acts as the container where the matched component will be rendered.
367
-
368
- ```
369
- <body>
370
- <nav>
371
- <a href="/" b-link>Home</a>
372
- <a href="/profile/123" b-link>Profile</a>
373
- </nav>
374
-
375
- <!-- Routed components appear here -->
376
- <lego-router></lego-router>
377
- </body>
378
-
379
- ```
380
-
381
- ## 📍 Basic Route Definition
382
-
383
- Routes are defined using `Lego.route(path, componentName)`.
384
-
385
- ```
386
- // Map the root path to 'home-page' block
387
- Lego.route('/', 'home-page');
388
-
389
- // Map /about to 'about-page' block
390
- Lego.route('/about', 'about-page');
391
-
392
- ```
393
-
394
- ## 动态 Dynamic Route Parameters
395
-
396
- You can define dynamic segments in your paths using the `:` prefix. These parameters are automatically parsed and injected into `Lego.globals.params`.
397
-
398
- ### Definition
399
-
400
- ```
401
- Lego.route('/user/:id', 'user-profile');
402
- Lego.route('/post/:category/:slug', 'blog-post');
403
-
404
- ```
405
-
406
- ### Usage inside a Component
407
-
408
- Any component can access these parameters via the `global` object.
409
-
410
- ```
411
- <template b-id="user-profile">
412
- <div>
413
- <h2>User Profile</h2>
414
- <p>Viewing ID: {{ global.params.id }}</p>
415
- </div>
416
- </template>
417
-
418
- ```
419
-
420
- ## 🛡 Navigation Middleware (Authentication)
421
-
422
- Middleware allows you to guard routes. The middleware function is executed before the component is rendered. If it returns `false`, the navigation is cancelled.
423
-
424
- ### Example: Auth Guard
425
-
426
- ```
427
- Lego.route('/admin', 'admin-dashboard', async (params, globals) => {
428
- const isAuthorized = globals.user && globals.user.role === 'admin';
429
-
430
- if (!isAuthorized) {
431
- // Redirect to login or home
432
- history.pushState({}, '', '/login');
433
- // We must manually trigger the router check after pushState
434
- Lego.init();
435
- return false; // Prevent 'admin-dashboard' from loading
436
- }
437
-
438
- return true; // Proceed to load the component
439
- });
440
-
441
- ```
442
-
443
- ## 🔗 Internal Navigation (`b-link`)
444
-
445
- To navigate without a full page refresh, use the `b-link` directive on anchor tags. This intercepts the click, updates the URL via `pushState`, and tells the Lego router to swap the view.
446
-
447
- ```
448
- <!-- This will trigger the router logic -->
449
- <a href="/dashboard" b-link>Go to Dashboard</a>
450
-
451
- <!-- This will trigger a standard browser reload -->
452
- <a href="/external-site.com">External Link</a>
453
-
454
- ```
455
-
456
- ## 🏗 Programmatic Navigation
457
-
458
- Sometimes you need to navigate via JavaScript (e.g., after a successful form submission). Use the standard `history.pushState` but remember that the library listens for the `popstate` event. To trigger a render manually, you can call the internal route matcher or simply use a helper:
459
-
460
- ```
461
- // In your component logic
462
- submitForm() {
463
- // Save data...
464
- history.pushState({}, '', '/success');
465
- // Dispatch popstate so the router hears it
466
- window.dispatchEvent(new PopStateEvent('popstate'));
467
- }
468
-
469
- ```
470
-
471
- ## 📂 Large Scale Structure
472
-
473
- For larger projects, define your routes in a dedicated initialization file and ensure your page components are registered before the router starts.
474
-
475
- ```
476
- // router-config.js
477
- import './views/home.lego';
478
- import './views/login.lego';
479
- import './views/profile.lego';
480
-
481
- export const setupRouter = () => {
482
- Lego.route('/', 'home-view');
483
- Lego.route('/login', 'login-view');
484
-
485
- // Nested logic for clean organization
486
- Lego.route('/profile/:username', 'profile-view', (params) => {
487
- return !!params.username; // Basic validation
488
- });
489
- };
490
-
491
- ```
492
-
493
- ## 📝 Router State Summary
494
-
495
- Feature
496
-
497
- Syntax
498
-
499
- Description
500
-
501
- **Viewport**
502
-
503
- `<lego-router>`
504
-
505
- Where the content renders.
506
-
507
- **Directive**
508
-
509
- `b-link`
510
-
511
- Intercepts link clicks.
512
-
513
- **Globals**
514
-
515
- `global.params`
516
-
517
- Object containing URL variables.
518
-
519
- **Middleware**
520
-
521
- `(params, globals) => boolean`
522
-
523
- Logic to permit/block access.