eleva 1.1.0-alpha → 1.2.1-alpha

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.
package/README.md CHANGED
@@ -1,7 +1,6 @@
1
- # Eleva
1
+ # Eleva 🚀
2
2
 
3
- **A minimalist, lightweight, pure vanilla JavaScript frontend runtime framework.**
4
- _Built with love for native JavaScript—because sometimes, less really is more!_ 😊
3
+ Pure JavaScript, Pure Performance, Simply Elegant.
5
4
 
6
5
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
6
  [![Version](https://img.shields.io/npm/v/eleva.svg?style=flat)](https://www.npmjs.com/package/eleva)
@@ -10,12 +9,25 @@ _Built with love for native JavaScript—because sometimes, less really is more!
10
9
  [![Minified Size](https://badgen.net/bundlephobia/min/eleva@latest)](https://bundlephobia.com/package/eleva@latest)
11
10
  [![Gzipped Size](https://badgen.net/bundlephobia/minzip/eleva@latest)](https://bundlephobia.com/package/eleva@latest)
12
11
 
12
+ <br>
13
+ <br>
14
+
15
+ <p align="center">
16
+ <img src="./docs/imgs/Eleva Logo.png" alt="Eleva Logo" width="50%">
17
+ </p>
18
+
19
+ <br>
20
+ <br>
21
+
22
+ **A minimalist, lightweight, pure vanilla JavaScript frontend runtime framework.**
23
+ _Built with love for native JavaScript—because sometimes, less really is more!_ 😊
24
+
13
25
  <!-- [![](https://data.jsdelivr.com/v1/package/npm/eleva/badge)](https://www.jsdelivr.com/package/npm/eleva) -->
14
26
 
15
- > **Stability Notice**: This is `v1.1.0-alpha` - APIs may change significantly until the stable release.
27
+ > **Stability Notice**: This is `v1.2.0-alpha` - APIs may change significantly until the stable release.
16
28
  > Not recommended for production use yet. Follow the [versioning guide](#version-guide) for updates.
17
29
 
18
- **Version:** `1.1.0-alpha`
30
+ **Version:** `1.2.0-alpha`
19
31
 
20
32
  Welcome to Eleva! This is my humble, experimental playground for a fresh approach to frontend development. Eleva was born out of my genuine passion for pure vanilla JavaScript—no frameworks, no bloat, just the power of native code. I hope you'll have fun exploring, testing, and contributing to make Eleva even better. 🚀
21
33
 
@@ -23,7 +35,7 @@ Welcome to Eleva! This is my humble, experimental playground for a fresh approac
23
35
 
24
36
  ## Table of Contents
25
37
 
26
- - [Eleva](#eleva)
38
+ - [Eleva 🚀](#eleva-)
27
39
  - [Table of Contents](#table-of-contents)
28
40
  - [Introduction](#introduction)
29
41
  - [Design Philosophy](#design-philosophy)
@@ -127,9 +139,9 @@ Eleva is ideal for developers seeking a lightweight, flexible, and high-performa
127
139
 
128
140
  I believe in clear versioning that reflects the maturity of the project:
129
141
 
130
- - **Pre-release Versions (Alpha/Beta):** Early versions like `1.1.0-alpha` indicate the API is still evolving. Expect frequent updates and share your feedback!
142
+ - **Pre-release Versions (Alpha/Beta):** Early versions like `1.2.0-alpha` indicate the API is still evolving. Expect frequent updates and share your feedback!
131
143
  - **Semantic Versioning:** Once stable, I’ll follow semantic versioning strictly to clearly communicate any breaking changes.
132
- - **Fresh Start:** This release (`1.1.0-alpha`) marks a significant update with new features and improvements.
144
+ - **Fresh Start:** This release (`1.2.0-alpha`) marks a significant update with enhanced inline documentation, improved JSDoc annotations, and a refined mounting context that now includes an `emitter` property.
133
145
 
134
146
  ---
135
147
 
@@ -138,9 +150,9 @@ I believe in clear versioning that reflects the maturity of the project:
138
150
  I follow [Semantic Versioning (SemVer)](https://semver.org/):
139
151
 
140
152
  - **🔢 Major Version:** Breaking changes or major overhauls (e.g., from `1.0.0` to `2.0.0`).
141
- - **🔢 Minor Version:** New features in a backward-compatible manner (e.g., from `1.0.0` to `1.1.0`).
153
+ - **🔢 Minor Version:** New features in a backward-compatible manner (e.g., from `1.1.0` to `1.2.0`).
142
154
  - **🔢 Patch Version:** Backward-compatible bug fixes and minor improvements (e.g., `1.0.1`).
143
- - **📌 Pre-release Identifiers:** Suffixes like `-alpha`, `-beta`, or `-rc` denote unstable releases (e.g., `1.1.0-alpha`).
155
+ - **📌 Pre-release Identifiers:** Suffixes like `-alpha`, `-beta`, or `-rc` denote unstable releases (e.g., `1.2.0-alpha`).
144
156
 
145
157
  ---
146
158
 
@@ -148,7 +160,7 @@ I follow [Semantic Versioning (SemVer)](https://semver.org/):
148
160
 
149
161
  Eleva is crafted for performance:
150
162
 
151
- - **Lightweight:** Approximately ~4 KB minified and ~1.9 KB gzipped.
163
+ - **Lightweight:** Approximately ~4 KB minified and ~1.8 KB gzipped.
152
164
  - **Efficient Reactivity:** Signal-based updates ensure only necessary DOM parts are updated.
153
165
  - **Optimized Diffing:** Renderer efficiently patches changes without the overhead of a virtual DOM.
154
166
  - **No Bloat:** Pure vanilla JavaScript with zero dependencies keeps your project nimble.
@@ -159,14 +171,16 @@ Eleva is crafted for performance:
159
171
 
160
172
  Preliminary benchmarks illustrate Eleva’s efficiency compared to popular frameworks:
161
173
 
162
- | Framework | Bundle Size (minified) | Initial Load Time | DOM Update Speed |
163
- | --------- | ---------------------- | ----------------- | ---------------- |
164
- | **Eleva** | **~4 KB** | **~35 ms** | **~2 ms** |
165
- | React | ~110 KB | ~100 ms | ~4 ms |
166
- | Vue | ~80 KB | ~80 ms | ~3 ms |
167
- | Angular | ~500 KB | ~250 ms | ~6 ms |
174
+ | **Framework** | **Bundle Size** (KB) | **Initial Load Time** (ms) | **DOM Update Speed** (s) | **Peak Memory Usage** (KB) | **Overall Performance Score** (lower is better) |
175
+ | ----------------------------- | -------------------- | -------------------------- | ------------------------ | -------------------------- | ----------------------------------------------- |
176
+ | **Eleva** (Direct DOM) | **1.8** | **10** | **0.018** | **0.25** | **3.02 (Best)** |
177
+ | **React** (Virtual DOM) | 42 | 40 | 0.020 | 0.25 | 20.57 |
178
+ | **Vue** (Reactive State) | 33 | 35 | 0.021 | 3.10 | 17.78 |
179
+ | **Angular** (Two-way Binding) | 80 | 100 | 0.021 | 0.25 | 45.07 (Slowest) |
168
180
 
169
- > ⚠️ **Disclaimer:** Benchmarks are based on internal tests with a minimal counter component and may vary by project and environment.
181
+ Detailed [Benchmark Metrics Report](BENCHMARK.md)
182
+
183
+ > ⚠️ **Disclaimer:** Benchmarks are based on internal tests and may vary by project and environment.
170
184
 
171
185
  ---
172
186
 
@@ -226,8 +240,8 @@ app.component("HelloWorld", {
226
240
  template: ({ count }) => `
227
241
  <div>
228
242
  <h1>Hello, Eleva! 👋</h1>
229
- <p>Count: ${count}</p>
230
- <button @click="() => count++">Increment</button>
243
+ <p>Count: ${count.value}</p>
244
+ <button @click="() => count.value++">Increment</button>
231
245
  </div>
232
246
  `,
233
247
  });
@@ -236,6 +250,8 @@ app.component("HelloWorld", {
236
250
  app.mount(document.getElementById("app"), "HelloWorld");
237
251
  ```
238
252
 
253
+ Interactive Demo: [CodePen](https://codepen.io/tarekraafat/pen/GgRrxdY?editors=1010)
254
+
239
255
  ### UMD Example
240
256
 
241
257
  Include Eleva via a script tag and use the global variable:
@@ -249,7 +265,7 @@ Include Eleva via a script tag and use the global variable:
249
265
  </head>
250
266
  <body>
251
267
  <div id="app"></div>
252
- <script src="https://unpkg.com/eleva/dist/eleva.min.js"></script>
268
+ <script src="https://cdn.jsdelivr.net/npm/eleva/dist/eleva.min.js"></script>
253
269
  <script>
254
270
  const app = new Eleva("MyApp");
255
271
  app.component("HelloWorld", {
@@ -260,8 +276,8 @@ Include Eleva via a script tag and use the global variable:
260
276
  template: ({ count }) => `
261
277
  <div>
262
278
  <h1>Hello, Eleva! 👋</h1>
263
- <p>Count: ${count}</p>
264
- <button @click="() => count++">Increment</button>
279
+ <p>Count: ${count.value}</p>
280
+ <button @click="() => count.value++">Increment</button>
265
281
  </div>
266
282
  `,
267
283
  });
@@ -271,6 +287,8 @@ Include Eleva via a script tag and use the global variable:
271
287
  </html>
272
288
  ```
273
289
 
290
+ Interactive Demo: [CodePen](https://codepen.io/tarekraafat/pen/jEOyzYN?editors=1010)
291
+
274
292
  ---
275
293
 
276
294
  ## API Reference
@@ -303,11 +321,11 @@ Include Eleva via a script tag and use the global variable:
303
321
  ### Renderer
304
322
 
305
323
  - **`patchDOM(container, newHtml)`**
306
- Efficiently update the DOM.
324
+ Efficiently updates the DOM.
307
325
  - **`diff(oldParent, newParent)`**
308
- Compare and update DOM trees.
326
+ Compares and updates DOM trees.
309
327
  - **`updateAttributes(oldEl, newEl)`**
310
- Sync element attributes.
328
+ Synchronizes element attributes.
311
329
 
312
330
  ### Eleva (Core)
313
331
 
@@ -319,7 +337,7 @@ Include Eleva via a script tag and use the global variable:
319
337
  Register a component.
320
338
  - **`.mount(container, compName, props)`**
321
339
  Mount a component to the DOM.
322
- _Note:_ This method now expects a DOM element (not a CSS selector) and supports both global component names (strings) and direct component definitions (objects). It returns a Promise, ensuring consistent asynchronous handling.
340
+ _Note:_ The mounting context now includes an `emitter` property (the full event emitter instance) for simplified event handling. Use `context.emitter.on(...)` and `context.emitter.emit(...)` for event management.
323
341
 
324
342
  For detailed API documentation, please check the [docs](docs/index.md) folder.
325
343
 
@@ -348,7 +366,7 @@ I welcome developers to dive in and experiment with Eleva! Here’s how to get s
348
366
  npm run dev
349
367
  ```
350
368
 
351
- 4. **Build for Production:**
369
+ 4. **Build for Production without TypeScript Declarations:**
352
370
 
353
371
  ```bash
354
372
  npm run build
@@ -361,6 +379,12 @@ I welcome developers to dive in and experiment with Eleva! Here’s how to get s
361
379
  npm run build:types:bundle
362
380
  ```
363
381
 
382
+ 6. **Build for Production with TypeScript Declarations:**
383
+
384
+ ```bash
385
+ npm run build:all
386
+ ```
387
+
364
388
  ---
365
389
 
366
390
  ## Testing
@@ -405,5 +429,5 @@ Eleva is open-source and available under the [MIT License](LICENSE).
405
429
 
406
430
  [Documentation](/docs/index.md) |
407
431
  [Examples](/examples) |
408
- [Changelog](/changelog.md) |
432
+ [Changelog](/CHANGELOG.md) |
409
433
  [GitHub Discussions](https://github.com/TarekRaafat/eleva/discussions)
package/dist/eleva.d.ts CHANGED
@@ -1,77 +1,25 @@
1
1
  /**
2
- * @class 🎙️ Emitter
3
- * @classdesc Robust inter-component communication with event bubbling.
4
- * Implements a basic publish-subscribe pattern for event handling, allowing components
5
- * to communicate through custom events.
6
- */
7
- declare class Emitter {
8
- /** @type {Object.<string, Function[]>} */
9
- events: {
10
- [x: string]: Function[];
11
- };
12
- /**
13
- * Registers an event handler for the specified event.
14
- *
15
- * @param {string} event - The name of the event.
16
- * @param {function(...any): void} handler - The function to call when the event is emitted.
17
- */
18
- on(event: string, handler: (...args: any[]) => void): void;
19
- /**
20
- * Removes a previously registered event handler.
21
- *
22
- * @param {string} event - The name of the event.
23
- * @param {function(...any): void} handler - The handler function to remove.
24
- */
25
- off(event: string, handler: (...args: any[]) => void): void;
26
- /**
27
- * Emits an event, invoking all handlers registered for that event.
28
- *
29
- * @param {string} event - The event name.
30
- * @param {...any} args - Additional arguments to pass to the event handlers.
31
- */
32
- emit(event: string, ...args: any[]): void;
33
- }
34
-
35
- /**
36
- * @class 🎨 Renderer
37
- * @classdesc Handles DOM patching, diffing, and attribute updates.
38
- * Provides methods for efficient DOM updates by diffing the new and old DOM structures
39
- * and applying only the necessary changes.
40
- */
41
- declare class Renderer {
42
- /**
43
- * Patches the DOM of a container element with new HTML content.
44
- *
45
- * @param {HTMLElement} container - The container element to patch.
46
- * @param {string} newHtml - The new HTML content to apply.
47
- */
48
- patchDOM(container: HTMLElement, newHtml: string): void;
49
- /**
50
- * Diffs two DOM trees (old and new) and applies updates to the old DOM.
51
- *
52
- * @param {HTMLElement} oldParent - The original DOM element.
53
- * @param {HTMLElement} newParent - The new DOM element.
54
- */
55
- diff(oldParent: HTMLElement, newParent: HTMLElement): void;
56
- /**
57
- * Updates the attributes of an element to match those of a new element.
58
- *
59
- * @param {HTMLElement} oldEl - The element to update.
60
- * @param {HTMLElement} newEl - The element providing the updated attributes.
61
- */
62
- updateAttributes(oldEl: HTMLElement, newEl: HTMLElement): void;
63
- }
64
-
65
- /**
2
+ * Defines the structure and behavior of a component.
66
3
  * @typedef {Object} ComponentDefinition
67
4
  * @property {function(Object<string, any>): (Object<string, any>|Promise<Object<string, any>>)} [setup]
68
- * A setup function that initializes the component state and returns an object or a promise that resolves to an object.
5
+ * Optional setup function that initializes the component's reactive state and lifecycle.
6
+ * Receives props and context as an argument and should return an object containing the component's state.
7
+ * Can return either a synchronous object or a Promise that resolves to an object for async initialization.
8
+ *
69
9
  * @property {function(Object<string, any>): string} template
70
- * A function that returns the HTML template string for the component.
10
+ * Required function that defines the component's HTML structure.
11
+ * Receives the merged context (props + setup data) and must return an HTML template string.
12
+ * Supports dynamic expressions using {{ }} syntax for reactive data binding.
13
+ *
71
14
  * @property {function(Object<string, any>): string} [style]
72
- * An optional function that returns scoped CSS styles as a string.
15
+ * Optional function that defines component-scoped CSS styles.
16
+ * Receives the merged context and returns a CSS string that will be automatically scoped to the component.
17
+ * Styles are injected into the component's container and only affect elements within it.
18
+ *
73
19
  * @property {Object<string, ComponentDefinition>} [children]
74
- * An optional mapping of CSS selectors to child component definitions.
20
+ * Optional object that defines nested child components.
21
+ * Keys are CSS selectors that match elements in the template where child components should be mounted.
22
+ * Values are ComponentDefinition objects that define the structure and behavior of each child component.
75
23
  */
76
24
  /**
77
25
  * @class 🧩 Eleva
@@ -88,24 +36,26 @@ declare class Eleva {
88
36
  constructor(name: string, config?: {
89
37
  [x: string]: any;
90
38
  });
91
- /** @type {string} */
39
+ /** @type {string} The unique identifier name for this Eleva instance */
92
40
  name: string;
93
- /** @type {Object<string, any>} */
41
+ /** @type {Object<string, any>} Optional configuration object for the Eleva instance */
94
42
  config: {
95
43
  [x: string]: any;
96
44
  };
97
- /** @type {Object<string, ComponentDefinition>} */
45
+ /** @type {Object<string, ComponentDefinition>} Object storing registered component definitions by name */
98
46
  _components: {
99
47
  [x: string]: ComponentDefinition;
100
48
  };
101
- /** @type {Array<Object>} */
102
- _plugins: Array<Object>;
103
- /** @private */
49
+ /** @private {Array<Object>} Collection of installed plugin instances */
50
+ private _plugins;
51
+ /** @private {string[]} Array of lifecycle hook names supported by the component */
104
52
  private _lifecycleHooks;
105
- /** @private {boolean} */
53
+ /** @private {boolean} Flag indicating if component is currently mounted */
106
54
  private _isMounted;
107
- emitter: Emitter;
108
- renderer: Renderer;
55
+ /** @private {Emitter} Instance of the event emitter for handling component events */
56
+ private emitter;
57
+ /** @private {Renderer} Instance of the renderer for handling DOM updates and patching */
58
+ private renderer;
109
59
  /**
110
60
  * Integrates a plugin with the Eleva framework.
111
61
  *
@@ -171,9 +121,14 @@ declare class Eleva {
171
121
  */
172
122
  private _mountChildren;
173
123
  }
124
+ /**
125
+ * Defines the structure and behavior of a component.
126
+ */
174
127
  type ComponentDefinition = {
175
128
  /**
176
- * A setup function that initializes the component state and returns an object or a promise that resolves to an object.
129
+ * Optional setup function that initializes the component's reactive state and lifecycle.
130
+ * Receives props and context as an argument and should return an object containing the component's state.
131
+ * Can return either a synchronous object or a Promise that resolves to an object for async initialization.
177
132
  */
178
133
  setup?: ((arg0: {
179
134
  [x: string]: any;
@@ -183,19 +138,25 @@ type ComponentDefinition = {
183
138
  [x: string]: any;
184
139
  }>)) | undefined;
185
140
  /**
186
- * A function that returns the HTML template string for the component.
141
+ * Required function that defines the component's HTML structure.
142
+ * Receives the merged context (props + setup data) and must return an HTML template string.
143
+ * Supports dynamic expressions using {{ }} syntax for reactive data binding.
187
144
  */
188
145
  template: (arg0: {
189
146
  [x: string]: any;
190
147
  }) => string;
191
148
  /**
192
- * An optional function that returns scoped CSS styles as a string.
149
+ * Optional function that defines component-scoped CSS styles.
150
+ * Receives the merged context and returns a CSS string that will be automatically scoped to the component.
151
+ * Styles are injected into the component's container and only affect elements within it.
193
152
  */
194
153
  style?: ((arg0: {
195
154
  [x: string]: any;
196
155
  }) => string) | undefined;
197
156
  /**
198
- * An optional mapping of CSS selectors to child component definitions.
157
+ * Optional object that defines nested child components.
158
+ * Keys are CSS selectors that match elements in the template where child components should be mounted.
159
+ * Values are ComponentDefinition objects that define the structure and behavior of each child component.
199
160
  */
200
161
  children?: {
201
162
  [x: string]: ComponentDefinition;
package/dist/eleva.esm.js CHANGED
@@ -56,7 +56,9 @@ class Signal {
56
56
  * @param {*} value - The initial value of the signal.
57
57
  */
58
58
  constructor(value) {
59
+ /** @private {*} Internal storage for the signal's current value */
59
60
  this._value = value;
61
+ /** @private {Set<function>} Collection of callback functions to be notified when value changes */
60
62
  this._watchers = new Set();
61
63
  }
62
64
 
@@ -104,7 +106,7 @@ class Emitter {
104
106
  * Creates a new Emitter instance.
105
107
  */
106
108
  constructor() {
107
- /** @type {Object.<string, Function[]>} */
109
+ /** @type {Object.<string, Function[]>} Storage for event handlers mapped by event name */
108
110
  this.events = {};
109
111
  }
110
112
 
@@ -254,15 +256,27 @@ class Renderer {
254
256
  }
255
257
 
256
258
  /**
259
+ * Defines the structure and behavior of a component.
257
260
  * @typedef {Object} ComponentDefinition
258
261
  * @property {function(Object<string, any>): (Object<string, any>|Promise<Object<string, any>>)} [setup]
259
- * A setup function that initializes the component state and returns an object or a promise that resolves to an object.
262
+ * Optional setup function that initializes the component's reactive state and lifecycle.
263
+ * Receives props and context as an argument and should return an object containing the component's state.
264
+ * Can return either a synchronous object or a Promise that resolves to an object for async initialization.
265
+ *
260
266
  * @property {function(Object<string, any>): string} template
261
- * A function that returns the HTML template string for the component.
267
+ * Required function that defines the component's HTML structure.
268
+ * Receives the merged context (props + setup data) and must return an HTML template string.
269
+ * Supports dynamic expressions using {{ }} syntax for reactive data binding.
270
+ *
262
271
  * @property {function(Object<string, any>): string} [style]
263
- * An optional function that returns scoped CSS styles as a string.
272
+ * Optional function that defines component-scoped CSS styles.
273
+ * Receives the merged context and returns a CSS string that will be automatically scoped to the component.
274
+ * Styles are injected into the component's container and only affect elements within it.
275
+ *
264
276
  * @property {Object<string, ComponentDefinition>} [children]
265
- * An optional mapping of CSS selectors to child component definitions.
277
+ * Optional object that defines nested child components.
278
+ * Keys are CSS selectors that match elements in the template where child components should be mounted.
279
+ * Values are ComponentDefinition objects that define the structure and behavior of each child component.
266
280
  */
267
281
 
268
282
  /**
@@ -278,19 +292,21 @@ class Eleva {
278
292
  * @param {Object<string, any>} [config={}] - Optional configuration for the instance.
279
293
  */
280
294
  constructor(name, config = {}) {
281
- /** @type {string} */
295
+ /** @type {string} The unique identifier name for this Eleva instance */
282
296
  this.name = name;
283
- /** @type {Object<string, any>} */
297
+ /** @type {Object<string, any>} Optional configuration object for the Eleva instance */
284
298
  this.config = config;
285
- /** @type {Object<string, ComponentDefinition>} */
299
+ /** @type {Object<string, ComponentDefinition>} Object storing registered component definitions by name */
286
300
  this._components = {};
287
- /** @type {Array<Object>} */
301
+ /** @private {Array<Object>} Collection of installed plugin instances */
288
302
  this._plugins = [];
289
- /** @private */
303
+ /** @private {string[]} Array of lifecycle hook names supported by the component */
290
304
  this._lifecycleHooks = ["onBeforeMount", "onMount", "onBeforeUpdate", "onUpdate", "onUnmount"];
291
- /** @private {boolean} */
305
+ /** @private {boolean} Flag indicating if component is currently mounted */
292
306
  this._isMounted = false;
307
+ /** @private {Emitter} Instance of the event emitter for handling component events */
293
308
  this.emitter = new Emitter();
309
+ /** @private {Renderer} Instance of the renderer for handling DOM updates and patching */
294
310
  this.renderer = new Renderer();
295
311
  }
296
312
 
@@ -341,16 +357,33 @@ class Eleva {
341
357
  } else {
342
358
  throw new Error("Invalid component parameter.");
343
359
  }
360
+
361
+ /**
362
+ * Destructure the component definition to access core functionality.
363
+ * - setup: Optional function for component initialization and state management
364
+ * - template: Required function that returns the component's HTML structure
365
+ * - style: Optional function for component-scoped CSS styles
366
+ * - children: Optional object defining nested child components
367
+ */
344
368
  const {
345
369
  setup,
346
370
  template,
347
371
  style,
348
372
  children
349
373
  } = definition;
374
+
375
+ /**
376
+ * Creates the initial context object for the component instance.
377
+ * This context provides core functionality and will be merged with setup data.
378
+ * @type {Object<string, any>}
379
+ * @property {Object<string, any>} props - Component properties passed during mounting
380
+ * @property {Emitter} emitter - Event emitter instance for component event handling
381
+ * @property {function(any): Signal} signal - Factory function to create reactive Signal instances
382
+ * @property {Object<string, function(): void>} ...lifecycleHooks - Prepared lifecycle hook functions
383
+ */
350
384
  const context = {
351
385
  props,
352
- emit: this.emitter.emit.bind(this.emitter),
353
- on: this.emitter.on.bind(this.emitter),
386
+ emitter: this.emitter,
354
387
  signal: v => new Signal(v),
355
388
  ...this._prepareLifecycleHooks()
356
389
  };
@@ -391,6 +424,12 @@ class Eleva {
391
424
  mergedContext.onUpdate && mergedContext.onUpdate();
392
425
  }
393
426
  };
427
+
428
+ /**
429
+ * Sets up reactive watchers for all Signal instances in the component's data.
430
+ * When a Signal's value changes, the component will re-render to reflect the updates.
431
+ * Stores unsubscribe functions to clean up watchers when component unmounts.
432
+ */
394
433
  Object.values(data).forEach(val => {
395
434
  if (val instanceof Signal) watcherUnsubscribers.push(val.watch(render));
396
435
  });