lego-dom 1.3.4 → 1.4.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 (91) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/main.js +24 -3
  3. package/package.json +1 -1
  4. package/vite-plugin.js +0 -14
  5. package/.github/workflows/deploy-docs.yml +0 -56
  6. package/.legodom +0 -87
  7. package/docs/.vitepress/config.js +0 -161
  8. package/docs/api/config.md +0 -95
  9. package/docs/api/define.md +0 -58
  10. package/docs/api/directives.md +0 -50
  11. package/docs/api/globals.md +0 -29
  12. package/docs/api/index.md +0 -30
  13. package/docs/api/lifecycle.md +0 -40
  14. package/docs/api/route.md +0 -37
  15. package/docs/api/vite-plugin.md +0 -58
  16. package/docs/contributing/01-welcome.md +0 -38
  17. package/docs/contributing/02-registry.md +0 -133
  18. package/docs/contributing/03-batcher.md +0 -110
  19. package/docs/contributing/04-reactivity.md +0 -87
  20. package/docs/contributing/05-caching.md +0 -59
  21. package/docs/contributing/06-init.md +0 -136
  22. package/docs/contributing/07-observer.md +0 -72
  23. package/docs/contributing/08-snap.md +0 -140
  24. package/docs/contributing/09-diffing.md +0 -69
  25. package/docs/contributing/10-studs.md +0 -78
  26. package/docs/contributing/11-scanner.md +0 -117
  27. package/docs/contributing/12-render.md +0 -138
  28. package/docs/contributing/13-directives.md +0 -243
  29. package/docs/contributing/14-events.md +0 -57
  30. package/docs/contributing/15-router.md +0 -57
  31. package/docs/contributing/16-state.md +0 -47
  32. package/docs/contributing/17-legodom.md +0 -48
  33. package/docs/contributing/index.md +0 -24
  34. package/docs/examples/form.md +0 -42
  35. package/docs/examples/index.md +0 -104
  36. package/docs/examples/routing.md +0 -409
  37. package/docs/examples/sfc-showcase.md +0 -34
  38. package/docs/examples/todo-app.md +0 -383
  39. package/docs/guide/cdn-usage.md +0 -354
  40. package/docs/guide/components.md +0 -418
  41. package/docs/guide/directives.md +0 -539
  42. package/docs/guide/directory-structure.md +0 -248
  43. package/docs/guide/faq.md +0 -210
  44. package/docs/guide/getting-started.md +0 -262
  45. package/docs/guide/index.md +0 -88
  46. package/docs/guide/lifecycle.md +0 -525
  47. package/docs/guide/quick-start.md +0 -49
  48. package/docs/guide/reactivity.md +0 -415
  49. package/docs/guide/routing.md +0 -334
  50. package/docs/guide/server-side.md +0 -134
  51. package/docs/guide/sfc.md +0 -464
  52. package/docs/guide/templating.md +0 -388
  53. package/docs/index.md +0 -160
  54. package/docs/public/logo.svg +0 -17
  55. package/docs/router/basic-routing.md +0 -103
  56. package/docs/router/cold-entry.md +0 -91
  57. package/docs/router/history.md +0 -69
  58. package/docs/router/index.md +0 -73
  59. package/docs/router/resolver.md +0 -74
  60. package/docs/router/surgical-swaps.md +0 -134
  61. package/docs/tutorial/01-project-setup.md +0 -152
  62. package/docs/tutorial/02-your-first-component.md +0 -226
  63. package/docs/tutorial/03-adding-routes.md +0 -279
  64. package/docs/tutorial/04-multi-page-app.md +0 -329
  65. package/docs/tutorial/05-state-and-globals.md +0 -285
  66. package/docs/tutorial/index.md +0 -40
  67. package/examples/vite-app/README.md +0 -71
  68. package/examples/vite-app/index.html +0 -42
  69. package/examples/vite-app/package.json +0 -18
  70. package/examples/vite-app/src/app.css +0 -3
  71. package/examples/vite-app/src/app.js +0 -29
  72. package/examples/vite-app/src/components/app-navbar.lego +0 -34
  73. package/examples/vite-app/src/components/customers/customer-details.lego +0 -24
  74. package/examples/vite-app/src/components/customers/customer-orders.lego +0 -21
  75. package/examples/vite-app/src/components/customers/order-list.lego +0 -55
  76. package/examples/vite-app/src/components/greeting-card.lego +0 -41
  77. package/examples/vite-app/src/components/sample-component.lego +0 -75
  78. package/examples/vite-app/src/components/shells/customers-shell.lego +0 -21
  79. package/examples/vite-app/src/components/side-menu.lego +0 -46
  80. package/examples/vite-app/src/components/todo-list.lego +0 -239
  81. package/examples/vite-app/src/components/widgets/user-card.lego +0 -27
  82. package/examples/vite-app/vite.config.js +0 -22
  83. package/tests/error.test.js +0 -74
  84. package/tests/main.test.js +0 -103
  85. package/tests/memory.test.js +0 -68
  86. package/tests/monitoring.test.js +0 -74
  87. package/tests/naming.test.js +0 -74
  88. package/tests/parse-lego.test.js +0 -65
  89. package/tests/security.test.js +0 -67
  90. package/tests/server.test.js +0 -114
  91. package/tests/syntax.test.js +0 -67
package/CHANGELOG.md CHANGED
@@ -2,6 +2,61 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.4.0] - 2026-01-16
6
+
7
+ ### Breaking Changes
8
+
9
+ - **`$ancestors()` now returns element instead of state:** For consistency with `$element`, `$ancestors()` now returns the ancestor element. Access state via `.state` property.
10
+ ```javascript
11
+ // Before (v1.3.x)
12
+ const userId = this.$ancestors('user-profile').userId;
13
+
14
+ // After (v1.4.0)
15
+ const userId = this.$ancestors('user-profile').state.userId;
16
+ ```
17
+ **Migration:** Add `.state` after all `$ancestors()` calls that access component state.
18
+
19
+ ## [1.3.5] - 2026-01-16
20
+
21
+ ### Features
22
+
23
+ - **Lego Studio:** Added zero-config component development environment. Enable with `Lego.init(document.body, { studio: true })` and navigate to `/_/studio` to browse, preview, and inspect components in real-time.
24
+ - Component browser with search/filter
25
+ - Live component preview in isolation
26
+ - Real-time state inspector with JSON editor
27
+ - URL deep linking for sharing components
28
+ - Published as separate package: `@legodom/studio@0.0.2`
29
+
30
+ - **Advanced API:** Exposed `Lego.snap()` and `Lego.unsnap()` for manual component initialization and cleanup. Useful for building dev tools, testing, and dynamic component creation in Shadow DOMs.
31
+ ```javascript
32
+ const el = document.createElement('my-component');
33
+ mount.appendChild(el);
34
+ Lego.snap(el); // Manually initialize
35
+
36
+ // Later...
37
+ Lego.unsnap(el); // Clean up
38
+ ```
39
+
40
+ - **Component State Property:** Added `element.state` getter/setter to all component instances for cleaner state access.
41
+ ```javascript
42
+ // Before (internal API)
43
+ const state = element._studs;
44
+
45
+ // After (public API)
46
+ const state = element.state;
47
+ element.state = { count: 5 }; // Merges into existing state
48
+ ```
49
+
50
+ ### Documentation
51
+
52
+ - **Advanced API Guide:** Added comprehensive documentation for `Lego.snap()` and `Lego.unsnap()` at `/docs/api/advanced.md`
53
+ - **Lego Studio Guide:** Added full Studio documentation at `/docs/guide/studio.md` with quick start, examples, and troubleshooting
54
+
55
+ ### Improvements
56
+
57
+ - **Studio CDN Loading:** Studio is loaded on-demand from unpkg CDN when `studio: true` is set, keeping core LegoDOM lightweight
58
+ - **State Reactivity:** The `element.state` setter uses `Object.assign()` to merge new values while preserving the reactive Proxy
59
+
5
60
  ## [1.3.4] - 2026-01-16
6
61
 
7
62
  ### Improvements
package/main.js CHANGED
@@ -193,11 +193,11 @@ const Lego = (() => {
193
193
  return current ?? '';
194
194
  };
195
195
 
196
- const findAncestorState = (el, tagName) => {
196
+ const findAncestor = (el, tagName) => {
197
197
  let parent = el.parentElement || el.getRootNode().host;
198
198
  while (parent) {
199
199
  if (parent.tagName && parent.tagName.toLowerCase() === tagName.toLowerCase()) {
200
- return parent._studs;
200
+ return parent;
201
201
  }
202
202
  parent = parent.parentElement || (parent.getRootNode && parent.getRootNode().host);
203
203
  }
@@ -231,7 +231,7 @@ const Lego = (() => {
231
231
  }
232
232
 
233
233
  const helpers = {
234
- $ancestors: (tag) => findAncestorState(context.self, tag),
234
+ $ancestors: (tag) => findAncestor(context.self, tag),
235
235
  $registry: (tag) => sharedStates.get(tag.toLowerCase()),
236
236
  $element: context.self,
237
237
  $route: Lego.globals.$route,
@@ -568,6 +568,13 @@ const Lego = (() => {
568
568
  get $go() { return Lego.globals.$go }
569
569
  }, el);
570
570
 
571
+ Object.defineProperty(el, 'state', {
572
+ get() { return this._studs },
573
+ set(v) { Object.assign(this._studs, v) },
574
+ configurable: true,
575
+ enumerable: false
576
+ });
577
+
571
578
  shadow.appendChild(tpl);
572
579
 
573
580
  const style = shadow.querySelector('style');
@@ -649,6 +656,8 @@ const Lego = (() => {
649
656
  };
650
657
 
651
658
  const publicAPI = {
659
+ snap,
660
+ unsnap,
652
661
  init: async (root = document.body, options = {}) => {
653
662
  if (!root || typeof root.nodeType !== 'number') root = document.body;
654
663
  styleConfig = options.styles || {};
@@ -706,6 +715,17 @@ const Lego = (() => {
706
715
  bind(root, root);
707
716
  render(root);
708
717
 
718
+ if (options.studio) {
719
+ if (!registry['lego-studio']) {
720
+ const script = document.createElement('script');
721
+ script.src = 'https://unpkg.com/@legodom/studio@0.0.2/dist/lego-studio.js';
722
+ script.onerror = () => console.warn('[Lego] Failed to load Studio from CDN');
723
+ document.head.appendChild(script);
724
+ }
725
+ Lego.route('/_/studio', 'lego-studio');
726
+ Lego.route('/_/studio/:component', 'lego-studio');
727
+ }
728
+
709
729
  if (routes.length > 0) {
710
730
  // Smart History: Restore surgical targets on Back button
711
731
  window.addEventListener('popstate', (event) => {
@@ -826,6 +846,7 @@ const Lego = (() => {
826
846
  },
827
847
  // For specific test validation
828
848
  getActiveComponentsCount: () => activeComponents.size,
849
+ getLegos: () => Object.keys(registry),
829
850
  config, // Expose config for customization
830
851
  route: (path, tagName, middleware = null) => {
831
852
  const paramNames = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lego-dom",
3
- "version": "1.3.4",
3
+ "version": "1.4.0",
4
4
  "license": "MIT",
5
5
  "description": "A feature-rich web components + SFC frontend framework",
6
6
  "main": "main.js",
package/vite-plugin.js CHANGED
@@ -153,20 +153,6 @@ export default '${parsed.componentName}';
153
153
  }
154
154
  },
155
155
 
156
- transform(code, id) {
157
- if (id.endsWith('.lego') && !id.includes('?')) {
158
- const parsed = parseLego(code, path.basename(id));
159
- const validation = validateLego(parsed);
160
-
161
- if (!validation.valid) {
162
- throw new Error(`Invalid .lego file:\n${validation.errors.join('\n')}`);
163
- }
164
156
 
165
- return {
166
- code: generateDefineCall(parsed),
167
- map: null
168
- };
169
- }
170
- }
171
157
  };
172
158
  }
@@ -1,56 +0,0 @@
1
- name: Deploy Documentation
2
-
3
- on:
4
- push:
5
- branches: [main]
6
- workflow_dispatch:
7
-
8
- permissions:
9
- contents: read
10
- pages: write
11
- id-token: write
12
-
13
- concurrency:
14
- group: pages
15
- cancel-in-progress: false
16
-
17
- jobs:
18
- build:
19
- runs-on: ubuntu-latest
20
- steps:
21
- - name: Checkout
22
- uses: actions/checkout@v4
23
- with:
24
- fetch-depth: 0
25
-
26
- - name: Setup Node
27
- uses: actions/setup-node@v4
28
- with:
29
- node-version: 20
30
- cache: npm
31
-
32
- - name: Setup Pages
33
- uses: actions/configure-pages@v4
34
-
35
- - name: Install dependencies
36
- run: npm ci
37
-
38
- - name: Build with VitePress
39
- run: npm run docs:build
40
-
41
- - name: Upload artifact
42
- uses: actions/upload-pages-artifact@v3
43
- with:
44
- path: docs/.vitepress/dist
45
-
46
- deploy:
47
- environment:
48
- name: github-pages
49
- url: ${{ steps.deployment.outputs.page_url }}
50
- needs: build
51
- runs-on: ubuntu-latest
52
- name: Deploy
53
- steps:
54
- - name: Deploy to GitHub Pages
55
- id: deployment
56
- uses: actions/deploy-pages@v4
package/.legodom DELETED
@@ -1,87 +0,0 @@
1
- # LegoDOM Framework Definition (.legodom)
2
-
3
- This file defines the valid syntax, API, and behavior of the LegoDOM framework. Use this context to write valid `.lego` components and understand the runtime behavior.
4
-
5
- ## 1. Component Structure (.lego)
6
- A `.lego` file is a Single File Component (SFC) composed of three sections:
7
-
8
- ```html
9
- <template b-styles="optional-style-id">
10
- <!-- HTML template with directives -->
11
- </template>
12
-
13
- <script>
14
- export default {
15
- // Reactive State
16
- count: 0,
17
-
18
- // Lifecycle Hooks
19
- mounted() { console.log('Mounted'); },
20
- updated() { console.log('State updated'); },
21
- unmounted() { console.log('Destroyed'); },
22
-
23
- // Methods
24
- increment() { this.count++ }
25
- }
26
- </script>
27
-
28
- <style>
29
- /* Scoped CSS. 'self' is replaced with ':host' automatically */
30
- self { display: block; }
31
- h1 { color: blue; }
32
- </style>
33
- ```
34
-
35
- ## 2. Template Directives
36
-
37
- | Directive | Syntax | Description |
38
- |-----------|--------|-------------|
39
- | **b-if** | `b-if="expr"` | Conditionally renders element if `expr` is truthy. Replaced by comment anchor if false. |
40
- | **b-show**| `b-show="expr"` | Toggles `display: none` based on `expr`. |
41
- | **b-for** | `b-for="item in list"` | Renders element for each item in `list`. `item` is available in scope. |
42
- | **b-text**| `b-text="path"` | Sets `textContent` to value at `path` (e.g. `user.name`). |
43
- | **b-html**| `b-html="expr"` | Sets `innerHTML` to result of `expr`. **Unsafe**. |
44
- | **b-sync**| `b-sync="path"` | Two-way binding for inputs. Updates `state.path` on input/change. |
45
- | **Event** | `@event="expr"` | Native event listener. `event` is available in scope. E.g. `@click="save()"`. |
46
- | **Interpolation** | `[[ expr ]]` | Text interpolation. Delimiters are `[[` and `]]` by default. |
47
-
48
- Note: `b-data` can be used on `<template>` or the custom element tag to inject initial state from JSON string.
49
-
50
- ## 3. Script Context & Helpers
51
- The `script` exports a default object which becomes the reactive state (`this`).
52
- Inside methods and template expressions, the following helpers are available:
53
-
54
- ### Scope
55
- - **this**: The reactive state of the component.
56
- - **event**: The native DOM event (only in `@event` handlers).
57
-
58
- ### Helpers
59
- - **$element**: The component's host DOM element.
60
- - **$emit(name, detail)**: Dispatches a CustomEvent `name` with `detail` (bubbles: true, composed: true).
61
- - **$go(path, ...targets)**: Router navigation helper. Returns object with method calls.
62
- - `this.$go('/url', '#target').get()`
63
- - `this.$go('/api', '#response').post({data})`
64
- - **$ancestors(tagName)**: Finds the state of the nearest ancestor component with `tagName`.
65
- - **$registry(tagName)**: Access shared state of logical-only components defined via `Lego.define`.
66
- - **$route**: Global route state object.
67
-
68
- ## 4. Router & Targets
69
- LegoDOM uses a "Target-Oriented" router. Navigation updates specific DOM elements (targets) rather than full page reloads.
70
-
71
- - **Definition**: `Lego.route('/path/:id', 'tag-name', middleware)`
72
- - **Targets**:
73
- - `string`: CSS selector (e.g., `#main`, `user-card`).
74
- - `function`: `(allComponents) => elements`
75
- - **Usage**:
76
- - HTML: `<a href="/path" b-target="#main">Link</a>` creates a surgical navigation link.
77
- - JS: `this.$go('/path', '#main').get()`
78
-
79
- ## 5. Lifecycle Hooks
80
- - **mounted()**: Called when the component is attached to DOM, shadow root created, and initial render complete.
81
- - **updated()**: Called after reactive state changes have been batched and applied to the DOM.
82
- - **unmounted()**: Called when component is removed from the DOM.
83
-
84
- ## 6. Global Configuration
85
- - `Lego.init(root, { styles: { ... }, loader: callback })`: Initializes the app.
86
- - `Lego.globals`: Global reactive state shared across all components.
87
- ```
@@ -1,161 +0,0 @@
1
- import { defineConfig } from 'vitepress';
2
-
3
- export default defineConfig({
4
- title: 'Lego',
5
- description: 'A feature-rich web components + SFC frontend framework',
6
- base: '/legodom/',
7
-
8
- themeConfig: {
9
- logo: '/logo.svg',
10
-
11
- nav: [
12
- { text: 'Guide', link: '/guide/' },
13
- { text: 'Tutorial', link: '/tutorial/' },
14
- { text: 'Contributing', link: '/contributing/' },
15
- { text: 'API', link: '/api/' },
16
- { text: 'Examples', link: '/examples/' },
17
- { text: 'Router', link: '/router/' },
18
- {
19
- text: 'v1.3.4',
20
- items: [
21
- { text: 'Changelog', link: 'https://github.com/rayattack/LegoDOM/releases' }
22
-
23
- ]
24
- }
25
- ],
26
-
27
- sidebar: {
28
- '/contributing/': [
29
- {
30
- text: 'Contributing',
31
- items: [
32
- { text: 'Topic 1 - Welcome', link: '/contributing/01-welcome' },
33
- { text: 'Topic 2 - The Registry', link: '/contributing/02-registry' },
34
- { text: 'Topic 3 - Batching', link: '/contributing/03-batcher' },
35
- { text: 'Topic 4 - Reactivity', link: '/contributing/04-reactivity' },
36
- { text: 'Topic 5 - Caching', link: '/contributing/05-caching' },
37
- { text: 'Topic 6 - LegoDOM Init', link: '/contributing/06-init' },
38
- { text: 'Topic 7 - Observer', link: '/contributing/07-observer' },
39
- { text: 'Topic 8 - Snap', link: '/contributing/08-snap' },
40
- { text: 'Topic 9 - Diffing', link: '/contributing/09-diffing' },
41
- { text: 'Topic 10 - State', 'link': '/contributing/10-studs' },
42
- { text: 'Topic 11 - Scanner', 'link': '/contributing/11-scanner' },
43
- { text: 'Topic 12 - Render', 'link': '/contributing/12-render' },
44
- { text: 'Topic 13 - Directives', 'link': '/contributing/13-directives' },
45
- { text: 'Topic 14 - Events', 'link': '/contributing/14-events' },
46
- { text: 'Topic 15 - Router', 'link': '/contributing/15-router' },
47
- { text: 'Topic 16 - State', 'link': '/contributing/16-state' },
48
- { text: 'Topic 17 - LegoDOM', 'link': '/contributing/17-legodom' },
49
- ]
50
- }
51
- ],
52
- '/tutorial/': [
53
- {
54
- text: 'Tutorial: Your First App',
55
- items: [
56
- { text: 'Overview', link: '/tutorial/' },
57
- { text: '1. Project Setup', link: '/tutorial/01-project-setup' },
58
- { text: '2. Your First Component', link: '/tutorial/02-your-first-component' },
59
- { text: '3. Adding Routes', link: '/tutorial/03-adding-routes' },
60
- { text: '4. Multi-Page App', link: '/tutorial/04-multi-page-app' },
61
- { text: '5. State & Globals', link: '/tutorial/05-state-and-globals' }
62
- ]
63
- }
64
- ],
65
- '/guide/': [
66
- {
67
- text: 'Introduction',
68
- items: [
69
- { text: 'What is LegoDOM?', link: '/guide/' },
70
- { text: 'Getting Started', link: '/guide/getting-started' },
71
- { text: 'Quick Start', link: '/guide/quick-start' },
72
- ]
73
- },
74
- {
75
- text: 'Core Concepts',
76
- items: [
77
- { text: 'Components', link: '/guide/components' },
78
- { text: 'Templating', link: '/guide/templating' },
79
- { text: 'Reactivity', link: '/guide/reactivity' },
80
- { text: 'Directives', link: '/guide/directives' }
81
- ]
82
- },
83
- {
84
- text: 'Advanced',
85
- items: [
86
- { text: 'Single File Components', link: '/guide/sfc' },
87
- { text: 'Routing', link: '/guide/routing' },
88
- { text: 'CDN Usage', link: '/guide/cdn-usage' },
89
- { text: 'Lifecycle Hooks', link: '/guide/lifecycle' },
90
- { text: 'Large Apps', link: '/guide/directory-structure' },
91
- { text: 'FAQ', link: '/guide/faq' }
92
- ]
93
- }
94
- ],
95
- '/api/': [
96
- {
97
- text: 'API Reference',
98
- items: [
99
- { text: 'Overview', link: '/api/' },
100
- { text: 'Lego.define()', link: '/api/define' },
101
- { text: 'Lego.route()', link: '/api/route' },
102
- { text: 'Lego.globals', link: '/api/globals' },
103
- { text: 'Lego.config', link: '/api/config' },
104
- { text: 'Directives', link: '/api/directives' },
105
- { text: 'Lifecycle Hooks', link: '/api/lifecycle' },
106
- { text: 'Vite Plugin', link: '/api/vite-plugin' }
107
- ]
108
- }
109
- ],
110
- '/router/': [
111
- {
112
- text: 'LegoDOM Router',
113
- items: [
114
- { text: 'About', link: '/router/' },
115
- { text: 'Basic Routing', link: '/router/basic-routing' },
116
- { text: 'Surgical Swaps', link: '/router/surgical-swaps' },
117
- { text: 'Cold Entry', link: '/router/cold-entry' },
118
- { text: 'History', link: '/router/history' }
119
- ]
120
- }
121
- ],
122
- '/examples/': [
123
- {
124
- text: 'Examples',
125
- items: [
126
- { text: 'Overview', link: '/examples/' },
127
- { text: 'Todo App', link: '/examples/todo-app' },
128
- { text: 'Routing Demo', link: '/examples/routing' },
129
- { text: 'SFC Showcase', link: '/examples/sfc-showcase' },
130
- { text: 'Form Validation', link: '/examples/form' }
131
- ]
132
- }
133
- ]
134
- },
135
-
136
- socialLinks: [
137
- { icon: 'github', link: 'https://github.com/rayattack/LegoDOM' }
138
- ],
139
-
140
- footer: {
141
- message: 'Released under the MIT License.',
142
- copyright: 'Copyright © 2024-present'
143
- },
144
-
145
- search: {
146
- provider: 'local'
147
- },
148
-
149
- editLink: {
150
- pattern: 'https://github.com/rayattack/LegoDOM/edit/main/docs/:path',
151
- text: 'Edit this page on GitHub'
152
- }
153
- },
154
-
155
- markdown: {
156
- theme: {
157
- light: 'github-light',
158
- dark: 'github-dark'
159
- }
160
- }
161
- });
@@ -1,95 +0,0 @@
1
- # Global Configuration
2
-
3
- `Lego.config` allows you to customize framework behavior, including error handling and metrics.
4
-
5
- ## Properties
6
-
7
- ### `syntax`
8
-
9
- * **Type**: `'mustache' | 'brackets'`
10
- * **Default**: `'brackets'`
11
-
12
- Configures the template delimiter style.
13
-
14
- * `'brackets'`: Uses <code v-pre>[[ variable ]]</code> (Default)
15
- * `'mustache'`: Uses <code v-pre>{{ variable }}</code> (Legacy/Vue-style)
16
-
17
- ```javascript
18
- // Switch back to mustache syntax if preferred
19
- Lego.config.syntax = 'mustache';
20
- ```
21
-
22
- ### `loader`
23
-
24
- * **Type**: `(tagName: string) => string | Promise<string> | null`
25
- * **Default**: `undefined`
26
-
27
- Use this hook to implement **Server-Side Component Delivery**.
28
-
29
- **Option 1: Simple Mode (Return URL)**
30
- We fetch it for you.
31
- ```javascript
32
- loader: (tag) => `/components/${tag}.lego`
33
- ```
34
-
35
- **Option 2: Power Mode (Return Promise)**
36
- You control the fetch. Useful for **Authentication** (Cookies, JWT) or Custom Headers.
37
-
38
- ```javascript
39
- Lego.init(document.body, {
40
- loader: async (tagName) => {
41
- // Custom Authenticated Fetch
42
- const res = await fetch(`/components/${tagName}.lego`, {
43
- credentials: 'include', // Send Cookies
44
- headers: { 'Authorization': getToken() }
45
- });
46
- return await res.text(); // Return SFC content directly
47
- }
48
- });
49
- ```
50
- **Mechanism:**
51
- 1. Browser sees unknown `<admin-widget>`.
52
- 2. `Lego` calls `config.loader('admin-widget')`.
53
- 3. If URL returned, it fetches the file.
54
- 4. The server returns raw SFC content (`<template>...`).
55
- 5. `Lego.defineSFC()` parses and upgrades the element instantly.
56
-
57
- ### `onError`
58
-
59
- * **Type**: `(error: Error, type: string, context: HTMLElement) => void`
60
- * **Default**: `undefined`
61
-
62
- Global error handler hook. Called when an error occurs during:
63
- * `render`: Template rendering (expression evaluation)
64
- * `event-handler`: `@event` callbacks
65
- * `define`: Component definition
66
- * `sync-update`: `b-sync` updates
67
-
68
- ```javascript
69
- Lego.config.onError = (err, type, context) => {
70
- console.error(`Error in ${type}:`, err);
71
- // Send to Sentry/Datadog
72
- captureException(err, { tags: { type } });
73
- };
74
- ```
75
-
76
- ### `metrics`
77
-
78
- * **Type**: `Object`
79
-
80
- Performance monitoring hooks, primarily used by plugins.
81
-
82
- * `onRenderStart(el)`: Called before a component renders.
83
- * `onRenderEnd(el)`: Called after a component finishes rendering.
84
-
85
- ```javascript
86
- // Example monitoring implementation
87
- Lego.config.metrics = {
88
- onRenderStart(el) {
89
- console.time(el.tagName);
90
- },
91
- onRenderEnd(el) {
92
- console.timeEnd(el.tagName);
93
- }
94
- };
95
- ```
@@ -1,58 +0,0 @@
1
- # Lego.define()
2
-
3
- Defining components in JavaScript.
4
-
5
- ## Type Signature
6
-
7
- ```ts
8
- Lego.define(tagName: string, template: string, state?: object)
9
- ```
10
-
11
- ## Arguments
12
-
13
- - **tagName**: The name of the custom element (must contain a hyphen).
14
- - **template**: The HTML string for the component. Can include `<style>`, markup, and bindings.
15
- - **state**: Initial state object and methods.
16
-
17
- ## Example
18
-
19
- ```js
20
- import { Lego } from 'lego-dom';
21
-
22
- Lego.define('user-card', `
23
- <div class="card">
24
- <h3>[[ name ]]</h3>
25
- <p>[[ role ]]</p>
26
- </div>
27
- `, {
28
- name: 'John Doe',
29
- role: 'Admin'
30
- });
31
- ```
32
-
33
- ## Lego.defineSFC()
34
-
35
- Runtime parser for Single File Components (SFC). Useful for **Server-Side Rendering** or dynamic loading architectures.
36
-
37
- ```ts
38
- Lego.defineSFC(content: string, filename?: string)
39
- ```
40
-
41
- ### Example
42
-
43
- ```javascript
44
- const sfc = `
45
- <template>
46
- <h1>[[ title ]]</h1>
47
- </template>
48
- <script>
49
- export default { title: 'Hello World' }
50
- </script>
51
- <style>
52
- h1 { color: red; }
53
- </style>
54
- `;
55
-
56
- // Registers <my-component> instantly
57
- Lego.defineSFC(sfc, 'my-component.lego');
58
- ```
@@ -1,50 +0,0 @@
1
- # Directives
2
-
3
- Special attributes that control DOM behavior.
4
-
5
- ## b-show
6
-
7
- Conditionally render an element.
8
-
9
- ```html
10
- <div b-show="loading">Loading...</div>
11
- <div b-show="!loading">Content loaded!</div>
12
- ```
13
-
14
- ## b-html
15
-
16
- Renders raw HTML. **Security Risk**: Use with caution.
17
-
18
- ```html
19
- <div b-html="htmlContent"></div>
20
- ```
21
-
22
- ## b-for
23
-
24
- Render a list of items.
25
-
26
- ```html
27
- <ul>
28
- <li b-for="user in users">
29
- [[ user.name ]]
30
- </li>
31
- </ul>
32
- ```
33
-
34
- ## b-sync
35
-
36
- Two-way data binding for form inputs.
37
-
38
- ```html
39
- <input b-sync="username" placeholder="Enter username">
40
- <p>You typed: [[ username ]]</p>
41
- ```
42
-
43
- ## @event
44
-
45
- Event listeners.
46
-
47
- ```html
48
- <button @click="save()">Save</button>
49
- <input @input="validate($event)">
50
- ```