eleva 1.0.1 → 1.1.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 (97) hide show
  1. package/README.md +21 -10
  2. package/dist/{eleva-plugins.cjs.js → eleva-plugins.cjs} +1002 -292
  3. package/dist/eleva-plugins.cjs.map +1 -0
  4. package/dist/eleva-plugins.d.cts +1352 -0
  5. package/dist/eleva-plugins.d.cts.map +1 -0
  6. package/dist/eleva-plugins.d.ts +1352 -0
  7. package/dist/eleva-plugins.d.ts.map +1 -0
  8. package/dist/{eleva-plugins.esm.js → eleva-plugins.js} +1002 -292
  9. package/dist/eleva-plugins.js.map +1 -0
  10. package/dist/eleva-plugins.umd.js +1001 -291
  11. package/dist/eleva-plugins.umd.js.map +1 -1
  12. package/dist/eleva-plugins.umd.min.js +1 -1
  13. package/dist/eleva-plugins.umd.min.js.map +1 -1
  14. package/dist/{eleva.cjs.js → eleva.cjs} +421 -191
  15. package/dist/eleva.cjs.map +1 -0
  16. package/dist/eleva.d.cts +1329 -0
  17. package/dist/eleva.d.cts.map +1 -0
  18. package/dist/eleva.d.ts +473 -226
  19. package/dist/eleva.d.ts.map +1 -0
  20. package/dist/{eleva.esm.js → eleva.js} +422 -192
  21. package/dist/eleva.js.map +1 -0
  22. package/dist/eleva.umd.js +420 -190
  23. package/dist/eleva.umd.js.map +1 -1
  24. package/dist/eleva.umd.min.js +1 -1
  25. package/dist/eleva.umd.min.js.map +1 -1
  26. package/dist/plugins/attr.cjs +279 -0
  27. package/dist/plugins/attr.cjs.map +1 -0
  28. package/dist/plugins/attr.d.cts +101 -0
  29. package/dist/plugins/attr.d.cts.map +1 -0
  30. package/dist/plugins/attr.d.ts +101 -0
  31. package/dist/plugins/attr.d.ts.map +1 -0
  32. package/dist/plugins/attr.js +276 -0
  33. package/dist/plugins/attr.js.map +1 -0
  34. package/dist/plugins/attr.umd.js +111 -22
  35. package/dist/plugins/attr.umd.js.map +1 -1
  36. package/dist/plugins/attr.umd.min.js +1 -1
  37. package/dist/plugins/attr.umd.min.js.map +1 -1
  38. package/dist/plugins/router.cjs +1873 -0
  39. package/dist/plugins/router.cjs.map +1 -0
  40. package/dist/plugins/router.d.cts +1296 -0
  41. package/dist/plugins/router.d.cts.map +1 -0
  42. package/dist/plugins/router.d.ts +1296 -0
  43. package/dist/plugins/router.d.ts.map +1 -0
  44. package/dist/plugins/router.js +1870 -0
  45. package/dist/plugins/router.js.map +1 -0
  46. package/dist/plugins/router.umd.js +482 -186
  47. package/dist/plugins/router.umd.js.map +1 -1
  48. package/dist/plugins/router.umd.min.js +1 -1
  49. package/dist/plugins/router.umd.min.js.map +1 -1
  50. package/dist/plugins/store.cjs +920 -0
  51. package/dist/plugins/store.cjs.map +1 -0
  52. package/dist/plugins/store.d.cts +266 -0
  53. package/dist/plugins/store.d.cts.map +1 -0
  54. package/dist/plugins/store.d.ts +266 -0
  55. package/dist/plugins/store.d.ts.map +1 -0
  56. package/dist/plugins/store.js +917 -0
  57. package/dist/plugins/store.js.map +1 -0
  58. package/dist/plugins/store.umd.js +410 -85
  59. package/dist/plugins/store.umd.js.map +1 -1
  60. package/dist/plugins/store.umd.min.js +1 -1
  61. package/dist/plugins/store.umd.min.js.map +1 -1
  62. package/package.json +112 -68
  63. package/src/core/Eleva.js +195 -115
  64. package/src/index.cjs +10 -0
  65. package/src/index.js +11 -0
  66. package/src/modules/Emitter.js +68 -20
  67. package/src/modules/Renderer.js +82 -20
  68. package/src/modules/Signal.js +43 -15
  69. package/src/modules/TemplateEngine.js +50 -9
  70. package/src/plugins/Attr.js +121 -19
  71. package/src/plugins/Router.js +526 -181
  72. package/src/plugins/Store.js +448 -69
  73. package/src/plugins/index.js +1 -0
  74. package/types/core/Eleva.d.ts +263 -169
  75. package/types/core/Eleva.d.ts.map +1 -1
  76. package/types/index.d.cts +3 -0
  77. package/types/index.d.cts.map +1 -0
  78. package/types/index.d.ts +5 -0
  79. package/types/index.d.ts.map +1 -1
  80. package/types/modules/Emitter.d.ts +73 -30
  81. package/types/modules/Emitter.d.ts.map +1 -1
  82. package/types/modules/Renderer.d.ts +48 -18
  83. package/types/modules/Renderer.d.ts.map +1 -1
  84. package/types/modules/Signal.d.ts +44 -16
  85. package/types/modules/Signal.d.ts.map +1 -1
  86. package/types/modules/TemplateEngine.d.ts +46 -11
  87. package/types/modules/TemplateEngine.d.ts.map +1 -1
  88. package/types/plugins/Attr.d.ts +83 -16
  89. package/types/plugins/Attr.d.ts.map +1 -1
  90. package/types/plugins/Router.d.ts +498 -207
  91. package/types/plugins/Router.d.ts.map +1 -1
  92. package/types/plugins/Store.d.ts +211 -37
  93. package/types/plugins/Store.d.ts.map +1 -1
  94. package/dist/eleva-plugins.cjs.js.map +0 -1
  95. package/dist/eleva-plugins.esm.js.map +0 -1
  96. package/dist/eleva.cjs.js.map +0 -1
  97. package/dist/eleva.esm.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Eleva.d.ts","sourceRoot":"","sources":["../../src/core/Eleva.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Eleva.d.ts","sourceRoot":"","sources":["../../src/core/Eleva.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export default Eleva;
2
+ import { Eleva } from "./core/Eleva.js";
3
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.cjs"],"names":[],"mappings":";sBAOsB,iBAAiB"}
package/types/index.d.ts CHANGED
@@ -1,3 +1,8 @@
1
+ export * from "./core/Eleva.js";
2
+ export { Emitter } from "./modules/Emitter.js";
3
+ export { Signal } from "./modules/Signal.js";
4
+ export { TemplateEngine } from "./modules/TemplateEngine.js";
5
+ export { Renderer } from "./modules/Renderer.js";
1
6
  export default Eleva;
2
7
  import { Eleva } from "./core/Eleva.js";
3
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":";sBAEsB,iBAAiB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":";;;;;;sBAOsB,iBAAiB"}
@@ -1,22 +1,45 @@
1
1
  /**
2
- * @template T
2
+ * @module eleva/emitter
3
+ * @fileoverview Event emitter for publish-subscribe communication between components.
4
+ */
5
+ /**
6
+ * Callback function invoked when an event is emitted.
3
7
  * @callback EventHandler
4
- * @param {...T} args - Event arguments
5
- * @returns {void|Promise<void>}
8
+ * @param {...any} args
9
+ * Event arguments passed to the handler.
10
+ * @returns {void | Promise<void>}
6
11
  */
7
12
  /**
13
+ * Function to unsubscribe an event handler.
8
14
  * @callback EventUnsubscribe
9
15
  * @returns {void}
10
16
  */
11
17
  /**
12
- * @typedef {`${string}:${string}`} EventName
13
- * Event names follow the format 'namespace:action' (e.g., 'user:login', 'cart:update')
18
+ * Event name string identifier.
19
+ * @typedef {string} EventName
20
+ * @description
21
+ * Recommended convention: 'namespace:action' (e.g., 'user:login').
22
+ * This pattern prevents naming collisions and improves code readability.
23
+ *
24
+ * Common namespaces:
25
+ * - `user:` - User-related events (login, logout, update)
26
+ * - `component:` - Component lifecycle events (mount, unmount)
27
+ * - `router:` - Navigation events (beforeEach, afterEach)
28
+ * - `store:` - State management events (change, error)
29
+ * @example
30
+ * 'user:login' // User logged in
31
+ * 'cart:update' // Shopping cart updated
32
+ * 'component:mount' // Component was mounted
14
33
  */
15
34
  /**
35
+ * Interface describing the public API of an Emitter.
16
36
  * @typedef {Object} EmitterLike
17
- * @property {function(string, EventHandler<unknown>): EventUnsubscribe} on - Subscribe to an event
18
- * @property {function(string, EventHandler<unknown>=): void} off - Unsubscribe from an event
19
- * @property {function(string, ...unknown): void} emit - Emit an event
37
+ * @property {(event: string, handler: EventHandler) => EventUnsubscribe} on
38
+ * Subscribe to an event.
39
+ * @property {(event: string, handler?: EventHandler) => void} off
40
+ * Unsubscribe from an event.
41
+ * @property {(event: string, ...args: unknown[]) => void} emit
42
+ * Emit an event with arguments.
20
43
  */
21
44
  /**
22
45
  * @class 📡 Emitter
@@ -55,6 +78,7 @@
55
78
  * // Lifecycle events
56
79
  * emitter.on('component:mount', (component) => {});
57
80
  * emitter.on('component:unmount', (component) => {});
81
+ * // Note: These lifecycle names are conventions; Eleva core does not emit them by default.
58
82
  * // State events
59
83
  * emitter.on('state:change', (newState, oldState) => {});
60
84
  * // Navigation events
@@ -66,7 +90,7 @@ export class Emitter implements EmitterLike {
66
90
  /**
67
91
  * Map of event names to their registered handler functions
68
92
  * @private
69
- * @type {Map<string, Set<EventHandler<unknown>>>}
93
+ * @type {Map<string, Set<EventHandler>>}
70
94
  */
71
95
  private _events;
72
96
  /**
@@ -75,9 +99,10 @@ export class Emitter implements EmitterLike {
75
99
  * Event names should follow the format 'namespace:action' for consistency.
76
100
  *
77
101
  * @public
78
- * @template T
79
102
  * @param {string} event - The name of the event to listen for (e.g., 'user:login').
80
- * @param {EventHandler<T>} handler - The callback function to invoke when the event occurs.
103
+ * @param {EventHandler} handler - The callback function to invoke when the event occurs.
104
+ * Note: Handlers returning Promises are NOT awaited. For async operations,
105
+ * handle promise resolution within your handler.
81
106
  * @returns {EventUnsubscribe} A function to unsubscribe the event handler.
82
107
  *
83
108
  * @example
@@ -85,8 +110,8 @@ export class Emitter implements EmitterLike {
85
110
  * const unsubscribe = emitter.on('user:login', (user) => console.log(user));
86
111
  *
87
112
  * @example
88
- * // Typed handler
89
- * emitter.on('user:update', (/** @type {{id: number, name: string}} *\/ user) => {
113
+ * // Handler with typed parameter
114
+ * emitter.on('user:update', (user) => {
90
115
  * console.log(`User ${user.id}: ${user.name}`);
91
116
  * });
92
117
  *
@@ -94,16 +119,18 @@ export class Emitter implements EmitterLike {
94
119
  * // Cleanup
95
120
  * unsubscribe(); // Stops listening for the event
96
121
  */
97
- public on<T>(event: string, handler: EventHandler<T>): EventUnsubscribe;
122
+ public on(event: string, handler: EventHandler): EventUnsubscribe;
98
123
  /**
99
124
  * Removes an event handler for the specified event name.
100
- * If no handler is provided, all handlers for the event are removed.
101
125
  * Automatically cleans up empty event sets to prevent memory leaks.
102
126
  *
127
+ * Behavior varies based on whether handler is provided:
128
+ * - With handler: Removes only that specific handler function (O(1) Set deletion)
129
+ * - Without handler: Removes ALL handlers for the event (O(1) Map deletion)
130
+ *
103
131
  * @public
104
- * @template T
105
132
  * @param {string} event - The name of the event to remove handlers from.
106
- * @param {EventHandler<T>} [handler] - The specific handler function to remove.
133
+ * @param {EventHandler} [handler] - The specific handler to remove. If omitted, all handlers are removed.
107
134
  * @returns {void}
108
135
  *
109
136
  * @example
@@ -116,17 +143,24 @@ export class Emitter implements EmitterLike {
116
143
  * // Remove all handlers for an event
117
144
  * emitter.off('user:login');
118
145
  */
119
- public off<T>(event: string, handler?: EventHandler<T>): void;
146
+ public off(event: string, handler?: EventHandler): void;
120
147
  /**
121
148
  * Emits an event with the specified data to all registered handlers.
122
149
  * Handlers are called synchronously in the order they were registered.
123
150
  * If no handlers are registered for the event, the emission is silently ignored.
151
+ * Handlers that return promises are not awaited.
152
+ *
153
+ * Error propagation behavior:
154
+ * - If a handler throws synchronously, the error propagates immediately
155
+ * - Remaining handlers in the iteration are NOT called after an error
156
+ * - For error-resilient emission, wrap your emit call in try/catch
157
+ * - Async handler rejections are not caught (fire-and-forget)
124
158
  *
125
159
  * @public
126
- * @template T
127
160
  * @param {string} event - The name of the event to emit.
128
- * @param {...T} args - Optional arguments to pass to the event handlers.
161
+ * @param {...any} args - Optional arguments to pass to the event handlers.
129
162
  * @returns {void}
163
+ * @throws {Error} If a handler throws synchronously, the error propagates to the caller.
130
164
  *
131
165
  * @example
132
166
  * // Emit an event with data
@@ -140,26 +174,35 @@ export class Emitter implements EmitterLike {
140
174
  * // Emit without data
141
175
  * emitter.emit('app:ready');
142
176
  */
143
- public emit<T>(event: string, ...args: T[]): void;
177
+ public emit(event: string, ...args: any[]): void;
144
178
  }
145
- export type EventHandler<T> = (...args: T[]) => void | Promise<void>;
179
+ /**
180
+ * Callback function invoked when an event is emitted.
181
+ */
182
+ export type EventHandler = (...args: any[]) => void | Promise<void>;
183
+ /**
184
+ * Function to unsubscribe an event handler.
185
+ */
146
186
  export type EventUnsubscribe = () => void;
147
187
  /**
148
- * Event names follow the format 'namespace:action' (e.g., 'user:login', 'cart:update')
188
+ * Event name string identifier.
189
+ */
190
+ export type EventName = string;
191
+ /**
192
+ * Interface describing the public API of an Emitter.
149
193
  */
150
- export type EventName = `${string}:${string}`;
151
194
  export type EmitterLike = {
152
195
  /**
153
- * - Subscribe to an event
196
+ * Subscribe to an event.
154
197
  */
155
- on: (arg0: string, arg1: EventHandler<unknown>) => EventUnsubscribe;
198
+ on: (event: string, handler: EventHandler) => EventUnsubscribe;
156
199
  /**
157
- * - Unsubscribe from an event
200
+ * Unsubscribe from an event.
158
201
  */
159
- off: (arg0: string, arg1: EventHandler<unknown> | undefined) => void;
202
+ off: (event: string, handler?: EventHandler) => void;
160
203
  /**
161
- * - Emit an event
204
+ * Emit an event with arguments.
162
205
  */
163
- emit: (arg0: string, ...args: unknown[]) => void;
206
+ emit: (event: string, ...args: unknown[]) => void;
164
207
  };
165
208
  //# sourceMappingURL=Emitter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Emitter.d.ts","sourceRoot":"","sources":["../../src/modules/Emitter.js"],"names":[],"mappings":"AAMA;;;;;GAKG;AAEH;;;GAGG;AAEH;;;GAGG;AAEH;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,gCAFgB,WAAW;IAYvB;;;;OAIG;IACH,gBAAwB;IAG1B;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,UAnBa,CAAC,SACH,MAAM,WACN,YAAY,CAAC,CAAC,CAAC,GACb,gBAAgB,CAqB5B;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,WAfa,CAAC,SACH,MAAM,YACN,YAAY,CAAC,CAAC,CAAC,GACb,IAAI,CAqBhB;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,YAjBa,CAAC,SACH,MAAM,WACH,CAAC,EAAA,GACF,IAAI,CAiBhB;CACF;yBAhLY,CAAC,cAEA,CAAC,EAAA,KACF,IAAI,GAAC,OAAO,CAAC,IAAI,CAAC;qCAKlB,IAAI;;;;wBAIJ,GAAG,MAAM,IAAI,MAAM,EAAE;;;;;QAMpB,CAAS,IAAM,EAAN,MAAM,EAAE,IAAqB,EAArB,YAAY,CAAC,OAAO,CAAC,KAAG,gBAAgB;;;;SACzD,CAAS,IAAM,EAAN,MAAM,EAAE,IAAsB,EAAtB,YAAY,CAAC,OAAO,CAAC,YAAC,KAAG,IAAI;;;;UAC9C,CAAS,IAAM,EAAN,MAAM,KAAE,IAAU,EAAP,OAAO,EAAA,KAAG,IAAI"}
1
+ {"version":3,"file":"Emitter.d.ts","sourceRoot":"","sources":["../../src/modules/Emitter.js"],"names":[],"mappings":"AAEA;;;GAGG;AAUH;;;;;;GAMG;AAEH;;;;GAIG;AAMH;;;;;;;;;;;;;;;;GAgBG;AAMH;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,gCAFgB,WAAW;IAavB;;;;OAIG;IACH,gBAAwB;IAG1B;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,iBApBW,MAAM,WACN,YAAY,GAGV,gBAAgB,CAqB5B;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,kBAdW,MAAM,YACN,YAAY,GACV,IAAI,CAqBhB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,mBAjBW,MAAM,WACH,GAAG,EAAA,GACJ,IAAI,CAkBhB;CACF;;;;qCArNa,GAAG,EAAA,KAEJ,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;;;;qCAMpB,IAAI;;;;wBASJ,MAAM;;;;;;;;QAuBL,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK,gBAAgB;;;;SAE1D,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,IAAI;;;;UAE/C,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI"}
@@ -59,27 +59,41 @@ export class Renderer implements RendererLike {
59
59
  * @example
60
60
  * // Empty the container
61
61
  * renderer.patchDOM(container, '');
62
+ *
63
+ * @see _diff - Low-level diffing algorithm.
64
+ * @see _patchNode - Individual node patching.
62
65
  */
63
66
  public patchDOM(container: HTMLElement, newHtml: string): void;
64
67
  /**
65
68
  * Performs a diff between two DOM nodes and patches the old node to match the new node.
66
69
  * Uses a two-pointer algorithm with key-based reconciliation for optimal performance.
70
+ * This method modifies oldParent in-place - it is not a pure function.
71
+ *
72
+ * Algorithm details:
73
+ * 1. Early exit if both nodes have no children (O(1) leaf node optimization)
74
+ * 2. Convert NodeLists to arrays for indexed access
75
+ * 3. Initialize two-pointer indices (oldStart/oldEnd, newStart/newEnd)
76
+ * 4. While pointers haven't crossed:
77
+ * a. Skip null entries (from previous moves)
78
+ * b. If nodes match (same key+tag or same type+name): patch and advance
79
+ * c. On mismatch: lazily build key→node map for O(1) lookup
80
+ * d. If keyed match found: move existing node (preserves DOM identity)
81
+ * e. Otherwise: clone and insert new node
82
+ * 5. After loop: append remaining new nodes or remove remaining old nodes
67
83
  *
68
- * Algorithm overview:
69
- * 1. Compare children from start using two pointers
70
- * 2. For mismatches, build a key map lazily for O(1) lookup
71
- * 3. Move or insert nodes as needed
72
- * 4. Clean up remaining nodes at the end
84
+ * Complexity: O(n) for most cases, O(n²) worst case with no keys.
85
+ * Non-keyed elements are matched by position and tag name.
73
86
  *
74
87
  * @private
75
- * @param {HTMLElement} oldParent - The original DOM element to update.
76
- * @param {HTMLElement} newParent - The new DOM element with desired state.
88
+ * @param {Element} oldParent - The original DOM element to update (modified in-place).
89
+ * @param {Element} newParent - The new DOM element with desired state.
77
90
  * @returns {void}
78
91
  */
79
92
  private _diff;
80
93
  /**
81
94
  * Patches a single node, updating its content and attributes to match the new node.
82
- * Handles text nodes by updating nodeValue, and element nodes by updating attributes
95
+ * Handles text nodes (nodeType 3 / Node.TEXT_NODE) by updating nodeValue,
96
+ * and element nodes (nodeType 1 / Node.ELEMENT_NODE) by updating attributes
83
97
  * and recursively diffing children.
84
98
  *
85
99
  * Skips nodes that are managed by Eleva component instances to prevent interference
@@ -94,12 +108,20 @@ export class Renderer implements RendererLike {
94
108
  /**
95
109
  * Removes a node from its parent, with special handling for Eleva-managed elements.
96
110
  * Style elements with the `data-e-style` attribute are preserved to maintain
97
- * component-scoped styles across re-renders.
111
+ * component styles across re-renders. Without this protection, component styles
112
+ * would be removed during DOM diffing and lost until the next full re-render.
113
+ *
114
+ * @note Style tags persist for the component's entire lifecycle. If the template
115
+ * conditionally removes elements that the CSS rules target (e.g., `.foo` elements),
116
+ * the style rules remain but simply have no matching elements. This is expected
117
+ * behavior - styles are cleaned up when the component unmounts, not when individual
118
+ * elements are removed.
98
119
  *
99
120
  * @private
100
121
  * @param {HTMLElement} parent - The parent element containing the node.
101
122
  * @param {Node} node - The node to remove.
102
123
  * @returns {void}
124
+ * @see _injectStyles - Where data-e-style elements are created.
103
125
  */
104
126
  private _removeNode;
105
127
  /**
@@ -107,12 +129,16 @@ export class Renderer implements RendererLike {
107
129
  * Adds new attributes, updates changed values, and removes attributes no longer present.
108
130
  * Also syncs DOM properties that can diverge from attributes after user interaction.
109
131
  *
110
- * Event attributes (prefixed with `@`) are skipped as they are handled separately
111
- * by Eleva's event binding system.
132
+ * Processing order:
133
+ * 1. Iterate new attributes, skip @ prefixed (event) attributes
134
+ * 2. Update attribute if value changed
135
+ * 3. Sync corresponding DOM property if writable (handles boolean conversion)
136
+ * 4. Iterate old attributes in reverse, remove if not in new element
137
+ * 5. Sync SYNC_PROPS (value, checked, selected) from new to old element
112
138
  *
113
139
  * @private
114
- * @param {HTMLElement} oldEl - The original element to update.
115
- * @param {HTMLElement} newEl - The new element with target attributes.
140
+ * @param {Element} oldEl - The original element to update.
141
+ * @param {Element} newEl - The new element with target attributes.
116
142
  * @returns {void}
117
143
  */
118
144
  private _updateAttributes;
@@ -135,10 +161,11 @@ export class Renderer implements RendererLike {
135
161
  /**
136
162
  * Extracts the key attribute from a node if it exists.
137
163
  * Only element nodes (nodeType === 1) can have key attributes.
164
+ * Uses optional chaining for null-safe access.
138
165
  *
139
166
  * @private
140
- * @param {Node|null|undefined} node - The node to extract the key from.
141
- * @returns {string|null} The key attribute value, or null if not an element or no key.
167
+ * @param {Node | null | undefined} node - The node to extract the key from.
168
+ * @returns {string | null} The key attribute value, or null if not an element or no key.
142
169
  */
143
170
  private _getNodeKey;
144
171
  /**
@@ -146,7 +173,7 @@ export class Renderer implements RendererLike {
146
173
  * The map is built lazily only when needed (when a mismatch occurs during diffing).
147
174
  *
148
175
  * @private
149
- * @param {Array<ChildNode>} children - The array of child nodes to map.
176
+ * @param {ChildNode[]} children - The array of child nodes to map.
150
177
  * @param {number} start - The start index (inclusive) for mapping.
151
178
  * @param {number} end - The end index (inclusive) for mapping.
152
179
  * @returns {KeyMap} A Map of key strings to their corresponding DOM nodes.
@@ -154,12 +181,15 @@ export class Renderer implements RendererLike {
154
181
  private _createKeyMap;
155
182
  }
156
183
  /**
157
- * Map of key attribute values to their corresponding DOM nodes for O(1) lookup
184
+ * Map of key attribute values to their corresponding DOM nodes.
158
185
  */
159
186
  export type KeyMap = Map<string, Node>;
187
+ /**
188
+ * Interface describing the public API of a Renderer.
189
+ */
160
190
  export type RendererLike = {
161
191
  /**
162
- * - Patches the DOM with new HTML
192
+ * Patches the DOM with new HTML content.
163
193
  */
164
194
  patchDOM: (arg0: HTMLElement, arg1: string) => void;
165
195
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Renderer.d.ts","sourceRoot":"","sources":["../../src/modules/Renderer.js"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,iCAFgB,YAAY;IAYxB;;;;;OAKG;IACH,uBAAmD;IAGrD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,2BAhBW,WAAW,WACX,MAAM,GACJ,IAAI,CAmBhB;IAED;;;;;;;;;;;;;;OAcG;IACH,cAgEC;IAED;;;;;;;;;;;;OAYG;IACH,mBAYC;IAED;;;;;;;;;OASG;IACH,oBAIC;IAED;;;;;;;;;;;;OAYG;IACH,0BAqCC;IAED;;;;;;;;;;;;;;OAcG;IACH,oBAkBC;IAED;;;;;;;OAOG;IACH,oBAEC;IAED;;;;;;;;;OASG;IACH,sBAOC;CACF;;;;qBAjVY,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;;;;;cAMhB,CAAS,IAAW,EAAX,WAAW,EAAE,IAAM,EAAN,MAAM,KAAG,IAAI"}
1
+ {"version":3,"file":"Renderer.d.ts","sourceRoot":"","sources":["../../src/modules/Renderer.js"],"names":[],"mappings":"AAqDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,iCAFgB,YAAY;IAiBxB;;;;;OAKG;IACH,uBAAmD;IAGrD;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,2BAnBW,WAAW,WACX,MAAM,GACJ,IAAI,CAsBhB;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,cAgEC;IAED;;;;;;;;;;;;;OAaG;IACH,mBAYC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,oBAIC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,0BAqCC;IAED;;;;;;;;;;;;;;OAcG;IACH,oBAkBC;IAED;;;;;;;;OAQG;IACH,oBAEC;IAED;;;;;;;;;OASG;IACH,sBAOC;CACF;;;;qBArYY,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;;;;;;;;cAWhB,CAAS,IAAW,EAAX,WAAW,EAAE,IAAM,EAAN,MAAM,KAAG,IAAI"}
@@ -1,18 +1,30 @@
1
1
  /**
2
- * @template T
2
+ * @module eleva/signal
3
+ * @fileoverview Reactive Signal primitive for fine-grained state management and change notification.
4
+ */
5
+ /**
6
+ * Callback function invoked when a signal's value changes.
7
+ * @template T The type of value held by the signal.
3
8
  * @callback SignalWatcher
4
- * @param {T} value - The new value of the signal
9
+ * @param {T} value
10
+ * The new value of the signal.
5
11
  * @returns {void}
6
12
  */
7
13
  /**
14
+ * Function to unsubscribe a watcher from a signal.
8
15
  * @callback SignalUnsubscribe
9
- * @returns {boolean} True if the watcher was successfully removed
16
+ * @returns {boolean}
17
+ * True if the watcher was successfully removed, false if already removed.
18
+ * Safe to call multiple times (idempotent).
10
19
  */
11
20
  /**
12
- * @template T
21
+ * Interface describing the public API of a Signal.
22
+ * @template T The type of value held by the signal.
13
23
  * @typedef {Object} SignalLike
14
- * @property {T} value - The current value
15
- * @property {function(SignalWatcher<T>): SignalUnsubscribe} watch - Subscribe to changes
24
+ * @property {T} value
25
+ * The current value of the signal.
26
+ * @property {function(SignalWatcher<T>): SignalUnsubscribe} watch
27
+ * Subscribe to value changes.
16
28
  */
17
29
  /**
18
30
  * @class ⚡ Signal
@@ -23,7 +35,7 @@
23
35
  * Render batching is handled at the component level, not the signal level.
24
36
  * The class is generic, allowing type-safe handling of any value type T.
25
37
  *
26
- * @template T The type of value held by this signal
38
+ * @template T The type of value held by the signal.
27
39
  *
28
40
  * @example
29
41
  * // Basic usage
@@ -41,7 +53,6 @@
41
53
  *
42
54
  * @example
43
55
  * // With objects
44
- * /** @type {Signal<{x: number, y: number}>} *\/
45
56
  * const position = new Signal({ x: 0, y: 0 });
46
57
  * position.value = { x: 10, y: 20 }; // Triggers watchers
47
58
  *
@@ -52,6 +63,7 @@ export class Signal<T> implements SignalLike<T> {
52
63
  * Creates a new Signal instance with the specified initial value.
53
64
  *
54
65
  * @public
66
+ * @constructor
55
67
  * @param {T} value - The initial value of the signal.
56
68
  *
57
69
  * @example
@@ -61,12 +73,9 @@ export class Signal<T> implements SignalLike<T> {
61
73
  * const active = new Signal(true); // Signal<boolean>
62
74
  *
63
75
  * @example
64
- * // Complex types (use JSDoc for type inference)
65
- * /** @type {Signal<string[]>} *\/
66
- * const items = new Signal([]);
67
- *
68
- * /** @type {Signal<{id: number, name: string} | null>} *\/
69
- * const user = new Signal(null);
76
+ * // Complex types
77
+ * const items = new Signal([]); // Signal holding an array
78
+ * const user = new Signal(null); // Signal holding nullable object
70
79
  */
71
80
  constructor(value: T);
72
81
  /**
@@ -85,6 +94,10 @@ export class Signal<T> implements SignalLike<T> {
85
94
  * Sets a new value for the signal and synchronously notifies all registered watchers if the value has changed.
86
95
  * Synchronous notification preserves stack traces and ensures immediate value consistency.
87
96
  *
97
+ * Uses strict equality (===) for comparison. For objects/arrays, watchers are only notified
98
+ * if the reference changes, not if properties are mutated. To trigger updates with objects,
99
+ * assign a new reference: `signal.value = { ...signal.value, updated: true }`.
100
+ *
88
101
  * @public
89
102
  * @param {T} newVal - The new value to set.
90
103
  * @returns {void}
@@ -104,6 +117,8 @@ export class Signal<T> implements SignalLike<T> {
104
117
  * @public
105
118
  * @param {SignalWatcher<T>} fn - The callback function to invoke on value change.
106
119
  * @returns {SignalUnsubscribe} A function to unsubscribe the watcher.
120
+ * Returns true if watcher was removed, false if it wasn't registered.
121
+ * Safe to call multiple times (idempotent after first call).
107
122
  *
108
123
  * @example
109
124
  * // Basic watching
@@ -112,6 +127,7 @@ export class Signal<T> implements SignalLike<T> {
112
127
  * @example
113
128
  * // Stop watching
114
129
  * unsubscribe(); // Returns true if watcher was removed
130
+ * unsubscribe(); // Returns false (already removed, safe to call again)
115
131
  *
116
132
  * @example
117
133
  * // Multiple watchers
@@ -125,20 +141,32 @@ export class Signal<T> implements SignalLike<T> {
125
141
  * This preserves stack traces for debugging and ensures immediate
126
142
  * value consistency. Render batching is handled at the component level.
127
143
  *
144
+ * @note If a watcher throws, subsequent watchers are NOT called.
145
+ * The error propagates to the caller (the setter).
146
+ *
128
147
  * @private
129
148
  * @returns {void}
130
149
  */
131
150
  private _notify;
132
151
  }
152
+ /**
153
+ * Callback function invoked when a signal's value changes.
154
+ */
133
155
  export type SignalWatcher<T> = (value: T) => void;
156
+ /**
157
+ * Function to unsubscribe a watcher from a signal.
158
+ */
134
159
  export type SignalUnsubscribe = () => boolean;
160
+ /**
161
+ * Interface describing the public API of a Signal.
162
+ */
135
163
  export type SignalLike<T> = {
136
164
  /**
137
- * - The current value
165
+ * The current value of the signal.
138
166
  */
139
167
  value: T;
140
168
  /**
141
- * - Subscribe to changes
169
+ * Subscribe to value changes.
142
170
  */
143
171
  watch: (arg0: SignalWatcher<T>) => SignalUnsubscribe;
144
172
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Signal.d.ts","sourceRoot":"","sources":["../../src/modules/Signal.js"],"names":[],"mappings":"AAMA;;;;;GAKG;AAEH;;;GAGG;AAEH;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,oBAxBa,CAAC,aAsBE,UAAU,CAAC,CAAC;IAG1B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,mBAhBW,CAAC,EA6BX;IAZC;;;;OAIG;IACH,eAAmB;IACnB;;;;OAIG;IACH,kBAA0B;IAa5B;;;;;;;OAOG;IACH,yBAHW,CAAC,EAQX;IAvBD;;;;;OAKG;IACH,oBAFa,CAAC,CAIb;IAiBD;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,iBAjBW,aAAa,CAAC,CAAC,CAAC,GACd,iBAAiB,CAmB7B;IAED;;;;;;;OAOG;IACH,gBAEC;CACF;0BAtJY,CAAC,YAEH,CAAC,KACC,IAAI;sCAKJ,OAAO;uBAIP,CAAC;;;;WAEA,CAAC;;;;WACD,CAAS,IAAgB,EAAhB,aAAa,CAAC,CAAC,CAAC,KAAG,iBAAiB"}
1
+ {"version":3,"file":"Signal.d.ts","sourceRoot":"","sources":["../../src/modules/Signal.js"],"names":[],"mappings":"AAEA;;;GAGG;AAUH;;;;;;;GAOG;AAEH;;;;;;GAMG;AAMH;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,oBAvBa,CAAC,aAqBE,UAAU,CAAC,CAAC;IAG1B;;;;;;;;;;;;;;;;;OAiBG;IACH,mBAbW,CAAC,EA0BX;IAZC;;;;OAIG;IACH,eAAmB;IACnB;;;;OAIG;IACH,kBAA0B;IAa5B;;;;;;;;;;;OAWG;IACH,yBAHW,CAAC,EAQX;IA3BD;;;;;OAKG;IACH,oBAFa,CAAC,CAIb;IAqBD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,iBApBW,aAAa,CAAC,CAAC,CAAC,GACd,iBAAiB,CAsB7B;IAED;;;;;;;;;;OAUG;IACH,gBAEC;CACF;;;;0BAxKY,CAAC,YAEH,CAAC,KAEC,IAAI;;;;sCAMJ,OAAO;;;;uBAWP,CAAC;;;;WAEA,CAAC;;;;WAED,CAAS,IAAgB,EAAhB,aAAa,CAAC,CAAC,CAAC,KAAG,iBAAiB"}
@@ -1,14 +1,26 @@
1
1
  /**
2
+ * @module eleva/template-engine
3
+ * @fileoverview Expression evaluator for directive attributes and property bindings.
4
+ */
5
+ /**
6
+ * Data context object for expression evaluation.
2
7
  * @typedef {Record<string, unknown>} ContextData
3
- * Data context for expression evaluation
8
+ * @description Contains variables and functions available during template evaluation.
4
9
  */
5
10
  /**
11
+ * JavaScript expression string to be evaluated.
6
12
  * @typedef {string} Expression
7
- * A JavaScript expression to be evaluated in the data context
13
+ * @description A JavaScript expression evaluated against a ContextData object.
8
14
  */
9
15
  /**
16
+ * Result of evaluating an expression.
10
17
  * @typedef {unknown} EvaluationResult
11
- * The result of evaluating an expression (string, number, boolean, object, function, etc.)
18
+ * @description Can be string, number, boolean, object, function, or any JavaScript value.
19
+ */
20
+ /**
21
+ * Compiled expression function cached for performance.
22
+ * @typedef {(data: ContextData) => EvaluationResult} CompiledExpressionFunction
23
+ * @description Pre-compiled function that evaluates an expression against context data.
12
24
  */
13
25
  /**
14
26
  * @class 🔒 TemplateEngine
@@ -42,25 +54,44 @@ export class TemplateEngine {
42
54
  /**
43
55
  * Cache for compiled expression functions.
44
56
  * Stores compiled Function objects keyed by expression string for O(1) lookup.
57
+ * The cache persists for the application lifetime and is never cleared.
58
+ * This improves performance for repeated evaluations of the same expression.
59
+ *
60
+ * Memory consideration: For applications with highly dynamic expressions
61
+ * (e.g., user-generated), memory usage grows unbounded. This is typically
62
+ * not an issue for static templates where expressions are finite.
45
63
  *
46
64
  * @static
47
65
  * @private
48
- * @type {Map<string, Function>}
66
+ * @type {Map<string, CompiledExpressionFunction>}
49
67
  */
50
68
  private static _functionCache;
51
69
  /**
52
70
  * Evaluates an expression in the context of the provided data object.
53
71
  * Used for resolving `@event` handlers and `:prop` bindings.
72
+ * Non-string expressions are returned as-is.
54
73
  *
55
- * Note: This does not provide a true sandbox and evaluated expressions may access global scope.
56
- * The use of the `with` statement is necessary for expression evaluation but has security implications.
57
- * Only use with trusted templates. User input should never be directly interpolated.
74
+ * @security CRITICAL SECURITY WARNING
75
+ * This method is NOT sandboxed. It uses `new Function()` and `with` statement,
76
+ * allowing full access to the global scope. Potential attack vectors include:
77
+ * - Code injection via malicious expressions
78
+ * - XSS attacks if user input is used as expressions
79
+ * - Access to sensitive globals (window, document, fetch, etc.)
80
+ *
81
+ * ONLY use with developer-defined template strings.
82
+ * NEVER use with user-provided input or untrusted data.
83
+ *
84
+ * Mitigation strategies:
85
+ * - Always sanitize any user-generated content before rendering in templates
86
+ * - Use Content Security Policy (CSP) headers to restrict script execution
87
+ * - Keep expressions simple (property access, method calls) - avoid complex logic
58
88
  *
59
89
  * @public
60
90
  * @static
61
- * @param {Expression|unknown} expression - The expression to evaluate.
91
+ * @param {Expression | unknown} expression - The expression to evaluate.
62
92
  * @param {ContextData} data - The data context for evaluation.
63
93
  * @returns {EvaluationResult} The result of the evaluation, or empty string if evaluation fails.
94
+ * @note Evaluation failures return an empty string without throwing.
64
95
  *
65
96
  * @example
66
97
  * // Property access
@@ -95,15 +126,19 @@ export class TemplateEngine {
95
126
  public static evaluate(expression: Expression | unknown, data: ContextData): EvaluationResult;
96
127
  }
97
128
  /**
98
- * Data context for expression evaluation
129
+ * Data context object for expression evaluation.
99
130
  */
100
131
  export type ContextData = Record<string, unknown>;
101
132
  /**
102
- * A JavaScript expression to be evaluated in the data context
133
+ * JavaScript expression string to be evaluated.
103
134
  */
104
135
  export type Expression = string;
105
136
  /**
106
- * The result of evaluating an expression (string, number, boolean, object, function, etc.)
137
+ * Result of evaluating an expression.
107
138
  */
108
139
  export type EvaluationResult = unknown;
140
+ /**
141
+ * Compiled expression function cached for performance.
142
+ */
143
+ export type CompiledExpressionFunction = (data: ContextData) => EvaluationResult;
109
144
  //# sourceMappingURL=TemplateEngine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateEngine.d.ts","sourceRoot":"","sources":["../../src/modules/TemplateEngine.js"],"names":[],"mappings":"AAMA;;;GAGG;AAEH;;;GAGG;AAEH;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH;IACE;;;;;;;OAOG;IACH,8BAAkC;IAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;IACH,mCAlCW,UAAU,GAAC,OAAO,QAClB,WAAW,GACT,gBAAgB,CAkD5B;CACF;;;;0BApHY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;yBAKvB,MAAM;;;;+BAKN,OAAO"}
1
+ {"version":3,"file":"TemplateEngine.d.ts","sourceRoot":"","sources":["../../src/modules/TemplateEngine.js"],"names":[],"mappings":"AAEA;;;GAGG;AAUH;;;;GAIG;AAEH;;;;GAIG;AAEH;;;;GAIG;AAMH;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH;IACE;;;;;;;;;;;;;OAaG;IACH,8BAAkC;IAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwDG;IACH,mCAnCW,UAAU,GAAG,OAAO,QACpB,WAAW,GACT,gBAAgB,CAmD5B;CACF;;;;0BAnJY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;yBAMvB,MAAM;;;;+BAMN,OAAO;;;;yCAUP,CAAC,IAAI,EAAE,WAAW,KAAK,gBAAgB"}