eleva 1.0.0-rc.7 → 1.0.0-rc.9

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 (38) hide show
  1. package/README.md +6 -6
  2. package/dist/eleva-plugins.cjs.js +114 -42
  3. package/dist/eleva-plugins.cjs.js.map +1 -1
  4. package/dist/eleva-plugins.esm.js +114 -42
  5. package/dist/eleva-plugins.esm.js.map +1 -1
  6. package/dist/eleva-plugins.umd.js +114 -42
  7. package/dist/eleva-plugins.umd.js.map +1 -1
  8. package/dist/eleva-plugins.umd.min.js +2 -2
  9. package/dist/eleva-plugins.umd.min.js.map +1 -1
  10. package/dist/eleva.cjs.js +59 -54
  11. package/dist/eleva.cjs.js.map +1 -1
  12. package/dist/eleva.d.ts +63 -2
  13. package/dist/eleva.esm.js +59 -54
  14. package/dist/eleva.esm.js.map +1 -1
  15. package/dist/eleva.umd.js +59 -54
  16. package/dist/eleva.umd.js.map +1 -1
  17. package/dist/eleva.umd.min.js +2 -2
  18. package/dist/eleva.umd.min.js.map +1 -1
  19. package/dist/plugins/attr.umd.js +2 -2
  20. package/dist/plugins/attr.umd.js.map +1 -1
  21. package/dist/plugins/attr.umd.min.js +1 -1
  22. package/dist/plugins/attr.umd.min.js.map +1 -1
  23. package/dist/plugins/props.umd.js +15 -18
  24. package/dist/plugins/props.umd.js.map +1 -1
  25. package/dist/plugins/props.umd.min.js +1 -1
  26. package/dist/plugins/props.umd.min.js.map +1 -1
  27. package/dist/plugins/router.umd.js +25 -22
  28. package/dist/plugins/router.umd.js.map +1 -1
  29. package/dist/plugins/router.umd.min.js +1 -1
  30. package/dist/plugins/router.umd.min.js.map +1 -1
  31. package/dist/plugins/store.umd.js +71 -19
  32. package/dist/plugins/store.umd.js.map +1 -1
  33. package/dist/plugins/store.umd.min.js +1 -1
  34. package/dist/plugins/store.umd.min.js.map +1 -1
  35. package/package.json +17 -16
  36. package/src/core/Eleva.js +42 -27
  37. package/types/core/Eleva.d.ts +14 -2
  38. package/types/core/Eleva.d.ts.map +1 -1
package/README.md CHANGED
@@ -40,9 +40,9 @@ Pure JavaScript, Pure Performance, Simply Elegant.
40
40
  **A minimalist, lightweight, pure vanilla JavaScript frontend runtime framework.**
41
41
  _Built with love for native JavaScript and designed with a minimal core that can be extended through a powerful plugin system-because sometimes, less really is more!_ 😊
42
42
 
43
- > **Stability Notice**: This is `v1.0.0-rc.6` - The core functionality is stable. Seeking community feedback before the final v1.0.0 release.
43
+ > **Stability Notice**: This is `v1.0.0-rc.9` - The core functionality is stable. Seeking community feedback before the final v1.0.0 release.
44
44
 
45
- **Version:** `1.0.0-rc.6`
45
+ **Version:** `1.0.0-rc.9`
46
46
 
47
47
 
48
48
 
@@ -205,10 +205,10 @@ Preliminary benchmarks illustrate Eleva's efficiency compared to popular framewo
205
205
 
206
206
  | **Framework** | **Bundle Size** (KB) | **Initial Load Time** (ms) | **DOM Update Speed** (s) | **Peak Memory Usage** (KB) | **Overall Performance Score** (lower is better) |
207
207
  | ----------------------------- | -------------------- | -------------------------- | ------------------------ | -------------------------- | ----------------------------------------------- |
208
- | **Eleva** (Direct DOM) | **2** | **0.05** | **0.002** | **0.25** | **0.58 (Best)** |
209
- | **React** (Virtual DOM) | 4.1 | 5.34 | 0.020 | 0.25 | 9.71 |
210
- | **Vue** (Reactive State) | 45 | 4.72 | 0.021 | 3.10 | 13.21 |
211
- | **Angular** (Two-way Binding) | 62 | 5.26 | 0.021 | 0.25 | 16.88 (Slowest) |
208
+ | **Eleva** (Direct DOM) | **2** | **0.05** | **0.002** | **0.25** | **0.58 (Best)** |
209
+ | **React** (Virtual DOM) | 4.1 | 5.34 | 0.020 | 0.25 | 9.71 |
210
+ | **Vue** (Reactive State) | 45 | 4.72 | 0.021 | 3.10 | 13.21 |
211
+ | **Angular** (Two-way Binding) | 62 | 5.26 | 0.021 | 0.25 | 16.88 (Slowest) |
212
212
 
213
213
  Detailed [Benchmark Metrics Report](BENCHMARK.md)
214
214
 
@@ -1,4 +1,4 @@
1
- /*! Eleva Plugins v1.0.0-rc.7 | MIT License | https://elevajs.com */
1
+ /*! Eleva Plugins v1.0.0-rc.9 | MIT License | https://elevajs.com */
2
2
  'use strict';
3
3
 
4
4
  /**
@@ -129,7 +129,7 @@ const AttrPlugin = {
129
129
  if (hasProperty) {
130
130
  // Boolean attribute handling
131
131
  if (enableBoolean) {
132
- const isBoolean = typeof oldEl[prop] === "boolean" || (descriptor == null ? void 0 : descriptor.get) && typeof descriptor.get.call(oldEl) === "boolean";
132
+ const isBoolean = typeof oldEl[prop] === "boolean" || descriptor?.get && typeof descriptor.get.call(oldEl) === "boolean";
133
133
  if (isBoolean) {
134
134
  const boolValue = value !== "false" && (value === "" || value === prop || value === "true");
135
135
  oldEl[prop] = boolValue;
@@ -171,7 +171,7 @@ const AttrPlugin = {
171
171
 
172
172
  // Override the _patchNode method to use our attribute handler
173
173
  eleva.renderer._patchNode = function (oldNode, newNode) {
174
- if (oldNode != null && oldNode._eleva_instance) return;
174
+ if (oldNode?._eleva_instance) return;
175
175
  if (!this._isSameNode(oldNode, newNode)) {
176
176
  oldNode.replaceWith(newNode.cloneNode(true));
177
177
  return;
@@ -221,16 +221,18 @@ const AttrPlugin = {
221
221
  }
222
222
  };
223
223
 
224
- function _extends() {
225
- return _extends = Object.assign ? Object.assign.bind() : function (n) {
226
- for (var e = 1; e < arguments.length; e++) {
227
- var t = arguments[e];
228
- for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
229
- }
230
- return n;
231
- }, _extends.apply(null, arguments);
232
- }
224
+ /**
225
+ * @typedef {import('eleva').Eleva} Eleva
226
+ * @typedef {import('eleva').Signal} Signal
227
+ * @typedef {import('eleva').ComponentDefinition} ComponentDefinition
228
+ */
233
229
 
230
+ /**
231
+ * Simple error handler for the core router.
232
+ * Can be overridden by error handling plugins.
233
+ * Provides consistent error formatting and logging for router operations.
234
+ * @private
235
+ */
234
236
  const CoreErrorHandler = {
235
237
  /**
236
238
  * Handles router errors with basic formatting.
@@ -339,11 +341,12 @@ class Router {
339
341
  this.eleva = eleva;
340
342
 
341
343
  /** @type {RouterOptions} The merged router options. */
342
- this.options = _extends({
344
+ this.options = {
343
345
  mode: "hash",
344
346
  queryParam: "view",
345
- viewSelector: "root"
346
- }, options);
347
+ viewSelector: "root",
348
+ ...options
349
+ };
347
350
 
348
351
  /** @private @type {RouteDefinition[]} The processed list of route definitions. */
349
352
  this.routes = this._processRoutes(options.routes || []);
@@ -407,9 +410,10 @@ class Router {
407
410
  const processedRoutes = [];
408
411
  for (const route of routes) {
409
412
  try {
410
- processedRoutes.push(_extends({}, route, {
413
+ processedRoutes.push({
414
+ ...route,
411
415
  segments: this._parsePathIntoSegments(route.path)
412
- }));
416
+ });
413
417
  } catch (error) {
414
418
  this.errorHandler.warn(`Invalid path in route definition "${route.path || "undefined"}": ${error.message}`, {
415
419
  route,
@@ -664,12 +668,13 @@ class Router {
664
668
  return false;
665
669
  }
666
670
  }
667
- const to = _extends({}, toLocation, {
671
+ const to = {
672
+ ...toLocation,
668
673
  params: toMatch.params,
669
674
  meta: toMatch.route.meta || {},
670
675
  name: toMatch.route.name,
671
676
  matched: toMatch.route
672
- });
677
+ };
673
678
  try {
674
679
  // 1. Run all *pre-navigation* guards.
675
680
  const canNavigate = await this._runGuards(to, from, toMatch.route);
@@ -900,10 +905,7 @@ class Router {
900
905
  * @returns {Function} A getter function.
901
906
  */
902
907
  _createRouteGetter(property, defaultValue) {
903
- return () => {
904
- var _this$currentRoute$va, _this$currentRoute$va2;
905
- return (_this$currentRoute$va = (_this$currentRoute$va2 = this.currentRoute.value) == null ? void 0 : _this$currentRoute$va2[property]) != null ? _this$currentRoute$va : defaultValue;
906
- };
908
+ return () => this.currentRoute.value?.[property] ?? defaultValue;
907
909
  }
908
910
 
909
911
  /**
@@ -915,7 +917,8 @@ class Router {
915
917
  _wrapComponent(component) {
916
918
  const originalSetup = component.setup;
917
919
  const self = this;
918
- return _extends({}, component, {
920
+ return {
921
+ ...component,
919
922
  async setup(ctx) {
920
923
  ctx.router = {
921
924
  navigate: self.navigate.bind(self),
@@ -940,7 +943,7 @@ class Router {
940
943
  };
941
944
  return originalSetup ? await originalSetup(ctx) : {};
942
945
  }
943
- });
946
+ };
944
947
  }
945
948
 
946
949
  /**
@@ -1334,6 +1337,12 @@ const RouterPlugin = {
1334
1337
  * const result = TemplateEngine.parse(template, data); // Returns: "Hello, World!"
1335
1338
  */
1336
1339
  class TemplateEngine {
1340
+ /**
1341
+ * @private {RegExp} Regular expression for matching template expressions in the format {{ expression }}
1342
+ * @type {RegExp}
1343
+ */
1344
+ static expressionPattern = /\{\{\s*(.*?)\s*\}\}/g;
1345
+
1337
1346
  /**
1338
1347
  * Parses a template string, replacing expressions with their evaluated values.
1339
1348
  * Expressions are evaluated in the provided data context.
@@ -1372,16 +1381,11 @@ class TemplateEngine {
1372
1381
  if (typeof expression !== "string") return expression;
1373
1382
  try {
1374
1383
  return new Function("data", `with(data) { return ${expression}; }`)(data);
1375
- } catch (_unused) {
1384
+ } catch {
1376
1385
  return "";
1377
1386
  }
1378
1387
  }
1379
1388
  }
1380
- /**
1381
- * @private {RegExp} Regular expression for matching template expressions in the format {{ expression }}
1382
- * @type {RegExp}
1383
- */
1384
- TemplateEngine.expressionPattern = /\{\{\s*(.*?)\s*\}\}/g;
1385
1389
 
1386
1390
  /**
1387
1391
  * @class 🎯 PropsPlugin
@@ -1717,7 +1721,10 @@ const PropsPlugin = {
1717
1721
  });
1718
1722
 
1719
1723
  // Merge signal props with regular props (signal props take precedence)
1720
- enhancedProps = _extends({}, extractedProps, signalProps);
1724
+ enhancedProps = {
1725
+ ...extractedProps,
1726
+ ...signalProps
1727
+ };
1721
1728
  }
1722
1729
 
1723
1730
  // Create reactive props for non-signal props only
@@ -1736,7 +1743,10 @@ const PropsPlugin = {
1736
1743
  const reactiveNonSignalProps = createReactiveProps(nonSignalProps);
1737
1744
 
1738
1745
  // Merge signal props with reactive non-signal props
1739
- finalProps = _extends({}, reactiveNonSignalProps, enhancedProps);
1746
+ finalProps = {
1747
+ ...reactiveNonSignalProps,
1748
+ ...enhancedProps // Signal props take precedence
1749
+ };
1740
1750
  }
1741
1751
 
1742
1752
  /** @type {MountResult} */
@@ -1907,6 +1917,61 @@ const PropsPlugin = {
1907
1917
  }
1908
1918
  };
1909
1919
 
1920
+ /**
1921
+ * @class 🏪 StorePlugin
1922
+ * @classdesc A powerful reactive state management plugin for Eleva.js that enables sharing
1923
+ * reactive data across the entire application. The Store plugin provides a centralized,
1924
+ * reactive data store that can be accessed from any component's setup function.
1925
+ *
1926
+ * Core Features:
1927
+ * - Centralized reactive state management using Eleva's signal system
1928
+ * - Global state accessibility through component setup functions
1929
+ * - Namespace support for organizing store modules
1930
+ * - Built-in persistence with localStorage/sessionStorage support
1931
+ * - Action-based state mutations with validation
1932
+ * - Subscription system for reactive updates
1933
+ * - DevTools integration for debugging
1934
+ * - Plugin architecture for extensibility
1935
+ *
1936
+ * @example
1937
+ * // Install the plugin
1938
+ * const app = new Eleva("myApp");
1939
+ * app.use(StorePlugin, {
1940
+ * state: {
1941
+ * user: { name: "John", email: "john@example.com" },
1942
+ * counter: 0,
1943
+ * todos: []
1944
+ * },
1945
+ * actions: {
1946
+ * increment: (state) => state.counter.value++,
1947
+ * addTodo: (state, todo) => state.todos.value.push(todo),
1948
+ * setUser: (state, user) => state.user.value = user
1949
+ * },
1950
+ * persistence: {
1951
+ * enabled: true,
1952
+ * key: "myApp-store",
1953
+ * storage: "localStorage"
1954
+ * }
1955
+ * });
1956
+ *
1957
+ * // Use store in components
1958
+ * app.component("Counter", {
1959
+ * setup({ store }) {
1960
+ * return {
1961
+ * count: store.state.counter,
1962
+ * increment: () => store.dispatch("increment"),
1963
+ * user: store.state.user
1964
+ * };
1965
+ * },
1966
+ * template: (ctx) => `
1967
+ * <div>
1968
+ * <p>Hello ${ctx.user.value.name}!</p>
1969
+ * <p>Count: ${ctx.count.value}</p>
1970
+ * <button onclick="ctx.increment()">+</button>
1971
+ * </div>
1972
+ * `
1973
+ * });
1974
+ */
1910
1975
  const StorePlugin = {
1911
1976
  /**
1912
1977
  * Unique identifier for the plugin
@@ -1994,13 +2059,14 @@ const StorePlugin = {
1994
2059
  this.actions = {};
1995
2060
  this.subscribers = new Set();
1996
2061
  this.mutations = [];
1997
- this.persistence = _extends({
2062
+ this.persistence = {
1998
2063
  enabled: false,
1999
2064
  key: "eleva-store",
2000
2065
  storage: "localStorage",
2001
2066
  include: null,
2002
- exclude: null
2003
- }, persistence);
2067
+ exclude: null,
2068
+ ...persistence
2069
+ };
2004
2070
  this.devTools = devTools;
2005
2071
  this.onError = onError;
2006
2072
  this._initializeState(state, actions);
@@ -2020,7 +2086,9 @@ const StorePlugin = {
2020
2086
  });
2021
2087
 
2022
2088
  // Set up actions
2023
- this.actions = _extends({}, initialActions);
2089
+ this.actions = {
2090
+ ...initialActions
2091
+ };
2024
2092
  }
2025
2093
 
2026
2094
  /**
@@ -2048,7 +2116,9 @@ const StorePlugin = {
2048
2116
  });
2049
2117
 
2050
2118
  // Set up namespaced actions
2051
- this.actions[namespace] = _extends({}, moduleActions);
2119
+ this.actions[namespace] = {
2120
+ ...moduleActions
2121
+ };
2052
2122
  });
2053
2123
  }
2054
2124
 
@@ -2376,7 +2446,8 @@ const StorePlugin = {
2376
2446
  }
2377
2447
 
2378
2448
  // Create a wrapped component that injects store into setup
2379
- const wrappedComponent = _extends({}, componentDef, {
2449
+ const wrappedComponent = {
2450
+ ...componentDef,
2380
2451
  async setup(ctx) {
2381
2452
  // Inject store into the context with enhanced API
2382
2453
  ctx.store = {
@@ -2400,7 +2471,7 @@ const StorePlugin = {
2400
2471
  const result = originalSetup ? await originalSetup(ctx) : {};
2401
2472
  return result;
2402
2473
  }
2403
- });
2474
+ };
2404
2475
 
2405
2476
  // Call original mount with wrapped component
2406
2477
  return await originalMount.call(eleva, container, wrappedComponent, props);
@@ -2414,7 +2485,8 @@ const StorePlugin = {
2414
2485
  for (const [selector, childComponent] of Object.entries(children)) {
2415
2486
  const componentDef = typeof childComponent === "string" ? eleva._components.get(childComponent) || childComponent : childComponent;
2416
2487
  if (componentDef && typeof componentDef === "object") {
2417
- wrappedChildren[selector] = _extends({}, componentDef, {
2488
+ wrappedChildren[selector] = {
2489
+ ...componentDef,
2418
2490
  async setup(ctx) {
2419
2491
  // Inject store into the context with enhanced API
2420
2492
  ctx.store = {
@@ -2438,7 +2510,7 @@ const StorePlugin = {
2438
2510
  const result = originalSetup ? await originalSetup(ctx) : {};
2439
2511
  return result;
2440
2512
  }
2441
- });
2513
+ };
2442
2514
  } else {
2443
2515
  wrappedChildren[selector] = childComponent;
2444
2516
  }