eleva 1.0.0-rc.5 → 1.0.0-rc.6

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.
@@ -1,3 +1,3 @@
1
- /*! Eleva v1.0.0-rc.5 | MIT License | https://elevajs.com */
1
+ /*! Eleva v1.0.0-rc.6 | MIT License | https://elevajs.com */
2
2
  var e,t;e=this,t=function(){"use strict";class e{static expressionPattern=/\{\{\s*(.*?)\s*\}\}/g;static parse(e,t){return"string"!=typeof e?e:e.replace(this.expressionPattern,(e,n)=>this.evaluate(n,t))}static evaluate(e,t){if("string"!=typeof e)return e;try{return new Function("data",`with(data) { return ${e}; }`)(t)}catch{return""}}}class t{constructor(e){this._value=e,this._watchers=new Set,this._pending=!1}get value(){return this._value}set value(e){this._value!==e&&(this._value=e,this._notify())}watch(e){return this._watchers.add(e),()=>this._watchers.delete(e)}_notify(){this._pending||(this._pending=!0,queueMicrotask(()=>{this._watchers.forEach(e=>e(this._value)),this._pending=!1}))}}class n{constructor(){this._events=new Map}on(e,t){return this._events.has(e)||this._events.set(e,new Set),this._events.get(e).add(t),()=>this.off(e,t)}off(e,t){if(this._events.has(e))if(t){const n=this._events.get(e);n.delete(t),0===n.size&&this._events.delete(e)}else this._events.delete(e)}emit(e,...t){this._events.has(e)&&this._events.get(e).forEach(e=>e(...t))}}class s{constructor(){this._tempContainer=document.createElement("div")}patchDOM(e,t){if(!(e instanceof HTMLElement))throw new TypeError("Container must be an HTMLElement");if("string"!=typeof t)throw new TypeError("newHtml must be a string");try{this._tempContainer.innerHTML=t,this._diff(e,this._tempContainer)}catch(e){throw new Error(`Failed to patch DOM: ${e.message}`)}}_diff(e,t){if(e===t||e.isEqualNode?.(t))return;const n=Array.from(e.childNodes),s=Array.from(t.childNodes);let o=0,i=0,r=n.length-1,a=s.length-1,c=null;for(;o<=r&&i<=a;){let t=n[o],a=s[i];if(t)if(this._isSameNode(t,a))this._patchNode(t,a),o++,i++;else{c||(c=this._createKeyMap(n,o,r));const s=this._getNodeKey(a),l=s?c.get(s):null;l?(this._patchNode(l,a),e.insertBefore(l,t),n[n.indexOf(l)]=null):e.insertBefore(a.cloneNode(!0),t),i++}else t=n[++o]}if(o>r){const t=s[a+1]?n[o]:null;for(let n=i;n<=a;n++)s[n]&&e.insertBefore(s[n].cloneNode(!0),t)}else if(i>a)for(let t=o;t<=r;t++)n[t]&&this._removeNode(e,n[t])}_patchNode(e,t){e?._eleva_instance||(this._isSameNode(e,t)?e.nodeType===Node.ELEMENT_NODE?(this._updateAttributes(e,t),this._diff(e,t)):e.nodeType===Node.TEXT_NODE&&e.nodeValue!==t.nodeValue&&(e.nodeValue=t.nodeValue):e.replaceWith(t.cloneNode(!0)))}_removeNode(e,t){"STYLE"===t.nodeName&&t.hasAttribute("data-e-style")||e.removeChild(t)}_updateAttributes(e,t){const n=e.attributes,s=t.attributes;for(let t=0;t<s.length;t++){const{name:n,value:o}=s[t];n.startsWith("@")||e.getAttribute(n)!==o&&e.setAttribute(n,o)}for(let s=n.length-1;s>=0;s--){const o=n[s].name;t.hasAttribute(o)||e.removeAttribute(o)}}_isSameNode(e,t){if(!e||!t)return!1;const n=e.nodeType===Node.ELEMENT_NODE?e.getAttribute("key"):null,s=t.nodeType===Node.ELEMENT_NODE?t.getAttribute("key"):null;return n&&s?n===s:!n&&!s&&e.nodeType===t.nodeType&&e.nodeName===t.nodeName}_createKeyMap(e,t,n){const s=new Map;for(let o=t;o<=n;o++){const t=e[o],n=this._getNodeKey(t);n&&s.set(n,t)}return s}_getNodeKey(e){return e?.nodeType===Node.ELEMENT_NODE?e.getAttribute("key"):null}}return class{constructor(e,o={}){this.name=e,this.config=o,this.emitter=new n,this.signal=t,this.renderer=new s,this._components=new Map,this._plugins=new Map,this._isMounted=!1,this._componentCounter=0}use(e,t={}){this._plugins.set(e.name,e);const n=e.install(this,t);return void 0!==n?n:this}component(e,t){return this._components.set(e,t),this}async mount(n,s,o={}){if(!n)throw new Error(`Container not found: ${n}`);if(n._eleva_instance)return n._eleva_instance;const i="string"==typeof s?this._components.get(s):s;if(!i)throw new Error(`Component "${s}" not registered.`);const r="c"+ ++this._componentCounter,{setup:a,template:c,style:l,children:u}=i,h={props:o,emitter:this.emitter,signal:e=>new this.signal(e)},d="function"==typeof a?await a(h):{};return await(async s=>{const o={...h,...s},i=[],a=[],d=[];this._isMounted?await(o.onBeforeUpdate?.({container:n,context:o})):await(o.onBeforeMount?.({container:n,context:o}));const f=async()=>{const t="function"==typeof c?await c(o):c,s=e.parse(t,o);this.renderer.patchDOM(n,s),this._processEvents(n,o,d),l&&this._injectStyles(n,r,l,o),u&&await this._mountComponents(n,u,a),this._isMounted?await(o.onUpdate?.({container:n,context:o})):(await(o.onMount?.({container:n,context:o})),this._isMounted=!0)};for(const e of Object.values(s))e instanceof t&&i.push(e.watch(f));await f();const _={container:n,data:o,unmount:async()=>{await(o.onUnmount?.({container:n,context:o,cleanup:{watchers:i,listeners:d,children:a}}));for(const e of i)e();for(const e of d)e();for(const e of a)await e.unmount();n.innerHTML="",delete n._eleva_instance}};return n._eleva_instance=_,_})(d)}_processEvents(t,n,s){const o=t.querySelectorAll("*");for(const t of o){const o=t.attributes;for(let i=0;i<o.length;i++){const r=o[i];if(!r.name.startsWith("@"))continue;const a=r.name.slice(1),c=r.value,l=n[c]||e.evaluate(c,n);"function"==typeof l&&(t.addEventListener(a,l),t.removeAttribute(r.name),s.push(()=>t.removeEventListener(a,l)))}}}_injectStyles(t,n,s,o){const i="function"==typeof s?e.parse(s(o),o):s;let r=t.querySelector(`style[data-e-style="${n}"]`);r&&r.textContent===i||(r||(r=document.createElement("style"),r.setAttribute("data-e-style",n),t.appendChild(r)),r.textContent=i)}_extractProps(e){if(!e.attributes)return{};const t={},n=e.attributes;for(let s=n.length-1;s>=0;s--){const o=n[s];o.name.startsWith(":")&&(t[o.name.slice(1)]=o.value,e.removeAttribute(o.name))}return t}async _mountComponents(e,t,n){for(const[s,o]of Object.entries(t))if(s)for(const t of e.querySelectorAll(s)){if(!(t instanceof HTMLElement))continue;const e=this._extractProps(t),s=await this.mount(t,o,e);s&&!n.includes(s)&&n.push(s)}}}},"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Eleva=t();
3
3
  //# sourceMappingURL=eleva.umd.min.js.map
@@ -1,10 +1,72 @@
1
- /*! Eleva Props Plugin v1.0.0-rc.1 | MIT License | https://elevajs.com */
1
+ /*! Eleva Props Plugin v1.0.0-rc.2 | MIT License | https://elevajs.com */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4
4
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
5
5
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ElevaPropsPlugin = {}));
6
6
  })(this, (function (exports) { 'use strict';
7
7
 
8
+ /**
9
+ * @class 🔒 TemplateEngine
10
+ * @classdesc A secure template engine that handles interpolation and dynamic attribute parsing.
11
+ * Provides a safe way to evaluate expressions in templates while preventing XSS attacks.
12
+ * All methods are static and can be called directly on the class.
13
+ *
14
+ * @example
15
+ * const template = "Hello, {{name}}!";
16
+ * const data = { name: "World" };
17
+ * const result = TemplateEngine.parse(template, data); // Returns: "Hello, World!"
18
+ */
19
+ class TemplateEngine {
20
+ /**
21
+ * @private {RegExp} Regular expression for matching template expressions in the format {{ expression }}
22
+ * @type {RegExp}
23
+ */
24
+ static expressionPattern = /\{\{\s*(.*?)\s*\}\}/g;
25
+
26
+ /**
27
+ * Parses a template string, replacing expressions with their evaluated values.
28
+ * Expressions are evaluated in the provided data context.
29
+ *
30
+ * @public
31
+ * @static
32
+ * @param {string} template - The template string to parse.
33
+ * @param {Record<string, unknown>} data - The data context for evaluating expressions.
34
+ * @returns {string} The parsed template with expressions replaced by their values.
35
+ * @example
36
+ * const result = TemplateEngine.parse("{{user.name}} is {{user.age}} years old", {
37
+ * user: { name: "John", age: 30 }
38
+ * }); // Returns: "John is 30 years old"
39
+ */
40
+ static parse(template, data) {
41
+ if (typeof template !== "string") return template;
42
+ return template.replace(this.expressionPattern, (_, expression) => this.evaluate(expression, data));
43
+ }
44
+
45
+ /**
46
+ * Evaluates an expression in the context of the provided data object.
47
+ * Note: This does not provide a true sandbox and evaluated expressions may access global scope.
48
+ * The use of the `with` statement is necessary for expression evaluation but has security implications.
49
+ * Expressions should be carefully validated before evaluation.
50
+ *
51
+ * @public
52
+ * @static
53
+ * @param {string} expression - The expression to evaluate.
54
+ * @param {Record<string, unknown>} data - The data context for evaluation.
55
+ * @returns {unknown} The result of the evaluation, or an empty string if evaluation fails.
56
+ * @example
57
+ * const result = TemplateEngine.evaluate("user.name", { user: { name: "John" } }); // Returns: "John"
58
+ * const age = TemplateEngine.evaluate("user.age", { user: { age: 30 } }); // Returns: 30
59
+ */
60
+ static evaluate(expression, data) {
61
+ if (typeof expression !== "string") return expression;
62
+ try {
63
+ return new Function("data", `with(data) { return ${expression}; }`)(data);
64
+ } catch {
65
+ return "";
66
+ }
67
+ }
68
+ }
69
+
8
70
  /**
9
71
  * @class 🎯 PropsPlugin
10
72
  * @classdesc A plugin that extends Eleva's props data handling to support any type of data structure
@@ -63,7 +125,7 @@
63
125
  * Plugin version
64
126
  * @type {string}
65
127
  */
66
- version: "1.0.0-rc.1",
128
+ version: "1.0.0-rc.2",
67
129
  /**
68
130
  * Plugin description
69
131
  * @type {string}
@@ -293,6 +355,167 @@
293
355
  return await originalMount.call(eleva, container, compName, enhancedProps);
294
356
  };
295
357
 
358
+ // Override Eleva's _mountComponents method to enable signal reference passing
359
+ const originalMountComponents = eleva._mountComponents;
360
+
361
+ // Cache to store parent contexts by container element
362
+ const parentContextCache = new WeakMap();
363
+ // Store child instances that need signal linking
364
+ const pendingSignalLinks = new Set();
365
+ eleva._mountComponents = async (container, children, childInstances) => {
366
+ for (const [selector, component] of Object.entries(children)) {
367
+ if (!selector) continue;
368
+ for (const el of container.querySelectorAll(selector)) {
369
+ if (!(el instanceof HTMLElement)) continue;
370
+
371
+ // Extract props from DOM attributes
372
+ const extractedProps = eleva._extractProps(el);
373
+
374
+ // Get parent context to check for signal references
375
+ let enhancedProps = extractedProps;
376
+
377
+ // Try to find parent context by looking up the DOM tree
378
+ let parentContext = parentContextCache.get(container);
379
+ if (!parentContext) {
380
+ let currentElement = container;
381
+ while (currentElement && !parentContext) {
382
+ if (currentElement._eleva_instance && currentElement._eleva_instance.data) {
383
+ parentContext = currentElement._eleva_instance.data;
384
+ // Cache the parent context for future use
385
+ parentContextCache.set(container, parentContext);
386
+ break;
387
+ }
388
+ currentElement = currentElement.parentElement;
389
+ }
390
+ }
391
+ if (enableReactivity && parentContext) {
392
+ const signalProps = {};
393
+
394
+ // Check each extracted prop to see if there's a matching signal in parent context
395
+ Object.keys(extractedProps).forEach(propName => {
396
+ if (parentContext[propName] && parentContext[propName] instanceof eleva.signal) {
397
+ // Found a signal in parent context with the same name as the prop
398
+ // Pass the signal reference instead of creating a new one
399
+ signalProps[propName] = parentContext[propName];
400
+ }
401
+ });
402
+
403
+ // Merge signal props with regular props (signal props take precedence)
404
+ enhancedProps = {
405
+ ...extractedProps,
406
+ ...signalProps
407
+ };
408
+ }
409
+
410
+ // Create reactive props for non-signal props only
411
+ let finalProps = enhancedProps;
412
+ if (enableReactivity) {
413
+ // Only create reactive props for values that aren't already signals
414
+ const nonSignalProps = {};
415
+ Object.entries(enhancedProps).forEach(([key, value]) => {
416
+ if (!(value && typeof value === "object" && "value" in value && "watch" in value)) {
417
+ // This is not a signal, create a reactive prop for it
418
+ nonSignalProps[key] = value;
419
+ }
420
+ });
421
+
422
+ // Create reactive props only for non-signal values
423
+ const reactiveNonSignalProps = createReactiveProps(nonSignalProps);
424
+
425
+ // Merge signal props with reactive non-signal props
426
+ finalProps = {
427
+ ...reactiveNonSignalProps,
428
+ ...enhancedProps // Signal props take precedence
429
+ };
430
+ }
431
+
432
+ /** @type {MountResult} */
433
+ const instance = await eleva.mount(el, component, finalProps);
434
+ if (instance && !childInstances.includes(instance)) {
435
+ childInstances.push(instance);
436
+
437
+ // If we have extracted props but no parent context yet, mark for later signal linking
438
+ if (enableReactivity && Object.keys(extractedProps).length > 0 && !parentContext) {
439
+ pendingSignalLinks.add({
440
+ instance,
441
+ extractedProps,
442
+ container,
443
+ component
444
+ });
445
+ }
446
+ }
447
+ }
448
+ }
449
+
450
+ // After mounting all children, try to link signals for pending instances
451
+ if (enableReactivity && pendingSignalLinks.size > 0) {
452
+ for (const pending of pendingSignalLinks) {
453
+ const {
454
+ instance,
455
+ extractedProps,
456
+ container,
457
+ component
458
+ } = pending;
459
+
460
+ // Try to find parent context again
461
+ let parentContext = parentContextCache.get(container);
462
+ if (!parentContext) {
463
+ let currentElement = container;
464
+ while (currentElement && !parentContext) {
465
+ if (currentElement._eleva_instance && currentElement._eleva_instance.data) {
466
+ parentContext = currentElement._eleva_instance.data;
467
+ parentContextCache.set(container, parentContext);
468
+ break;
469
+ }
470
+ currentElement = currentElement.parentElement;
471
+ }
472
+ }
473
+ if (parentContext) {
474
+ const signalProps = {};
475
+
476
+ // Check each extracted prop to see if there's a matching signal in parent context
477
+ Object.keys(extractedProps).forEach(propName => {
478
+ if (parentContext[propName] && parentContext[propName] instanceof eleva.signal) {
479
+ signalProps[propName] = parentContext[propName];
480
+ }
481
+ });
482
+
483
+ // Update the child instance's data with signal references
484
+ if (Object.keys(signalProps).length > 0) {
485
+ Object.assign(instance.data, signalProps);
486
+
487
+ // Set up signal watchers for the newly linked signals
488
+ Object.keys(signalProps).forEach(propName => {
489
+ const signal = signalProps[propName];
490
+ if (signal && typeof signal.watch === "function") {
491
+ signal.watch(newValue => {
492
+ // Trigger a re-render of the child component when the signal changes
493
+ const childComponent = eleva._components.get(component) || component;
494
+ if (childComponent && childComponent.template) {
495
+ const templateResult = typeof childComponent.template === "function" ? childComponent.template(instance.data) : childComponent.template;
496
+ const newHtml = TemplateEngine.parse(templateResult, instance.data);
497
+ eleva.renderer.patchDOM(instance.container, newHtml);
498
+ }
499
+ });
500
+ }
501
+ });
502
+
503
+ // Initial re-render to show the correct signal values
504
+ const childComponent = eleva._components.get(component) || component;
505
+ if (childComponent && childComponent.template) {
506
+ const templateResult = typeof childComponent.template === "function" ? childComponent.template(instance.data) : childComponent.template;
507
+ const newHtml = TemplateEngine.parse(templateResult, instance.data);
508
+ eleva.renderer.patchDOM(instance.container, newHtml);
509
+ }
510
+ }
511
+
512
+ // Remove from pending list
513
+ pendingSignalLinks.delete(pending);
514
+ }
515
+ }
516
+ }
517
+ };
518
+
296
519
  /**
297
520
  * Expose utility methods on the Eleva instance
298
521
  * @namespace eleva.props
@@ -332,6 +555,7 @@
332
555
  // Store original methods for uninstall
333
556
  eleva._originalExtractProps = eleva._extractProps;
334
557
  eleva._originalMount = originalMount;
558
+ eleva._originalMountComponents = originalMountComponents;
335
559
  },
336
560
  /**
337
561
  * Uninstalls the plugin from the Eleva instance
@@ -360,6 +584,12 @@
360
584
  delete eleva._originalMount;
361
585
  }
362
586
 
587
+ // Restore original _mountComponents method
588
+ if (eleva._originalMountComponents) {
589
+ eleva._mountComponents = eleva._originalMountComponents;
590
+ delete eleva._originalMountComponents;
591
+ }
592
+
363
593
  // Remove plugin utility methods
364
594
  if (eleva.props) {
365
595
  delete eleva.props;
@@ -1 +1 @@
1
- {"version":3,"file":"props.umd.js","sources":["../../src/plugins/Props.js"],"sourcesContent":["\"use strict\";\n\n/**\n * @class 🎯 PropsPlugin\n * @classdesc A plugin that extends Eleva's props data handling to support any type of data structure\n * with automatic type detection, parsing, and reactive prop updates. This plugin enables seamless\n * passing of complex data types from parent to child components without manual parsing.\n *\n * Core Features:\n * - Automatic type detection and parsing (strings, numbers, booleans, objects, arrays, dates, etc.)\n * - Support for complex data structures including nested objects and arrays\n * - Reactive props that automatically update when parent data changes\n * - Comprehensive error handling with custom error callbacks\n * - Simple configuration with minimal setup required\n *\n * @example\n * // Install the plugin\n * const app = new Eleva(\"myApp\");\n * app.use(PropsPlugin, {\n * enableAutoParsing: true,\n * enableReactivity: true,\n * onError: (error, value) => {\n * console.error('Props parsing error:', error, value);\n * }\n * });\n *\n * // Use complex props in components\n * app.component(\"UserCard\", {\n * template: (ctx) => `\n * <div class=\"user-info-container\"\n * :user='${JSON.stringify(ctx.user.value)}'\n * :permissions='${JSON.stringify(ctx.permissions.value)}'\n * :settings='${JSON.stringify(ctx.settings.value)}'>\n * </div>\n * `,\n * children: {\n * '.user-info-container': 'UserInfo'\n * }\n * });\n *\n * app.component(\"UserInfo\", {\n * setup({ props }) {\n * return {\n * user: props.user, // Automatically parsed object\n * permissions: props.permissions, // Automatically parsed array\n * settings: props.settings // Automatically parsed object\n * };\n * }\n * });\n */\nexport const PropsPlugin = {\n /**\n * Unique identifier for the plugin\n * @type {string}\n */\n name: \"props\",\n\n /**\n * Plugin version\n * @type {string}\n */\n version: \"1.0.0-rc.1\",\n\n /**\n * Plugin description\n * @type {string}\n */\n description:\n \"Advanced props data handling for complex data structures with automatic type detection and reactivity\",\n\n /**\n * Installs the plugin into the Eleva instance\n *\n * @param {Object} eleva - The Eleva instance\n * @param {Object} options - Plugin configuration options\n * @param {boolean} [options.enableAutoParsing=true] - Enable automatic type detection and parsing\n * @param {boolean} [options.enableReactivity=true] - Enable reactive prop updates using Eleva's signal system\n * @param {Function} [options.onError=null] - Error handler function called when parsing fails\n *\n * @example\n * // Basic installation\n * app.use(PropsPlugin);\n *\n * // Installation with custom options\n * app.use(PropsPlugin, {\n * enableAutoParsing: true,\n * enableReactivity: false,\n * onError: (error, value) => {\n * console.error('Props parsing error:', error, value);\n * }\n * });\n */\n install(eleva, options = {}) {\n const {\n enableAutoParsing = true,\n enableReactivity = true,\n onError = null,\n } = options;\n\n /**\n * Detects the type of a given value\n * @private\n * @param {any} value - The value to detect type for\n * @returns {string} The detected type ('string', 'number', 'boolean', 'object', 'array', 'date', 'map', 'set', 'function', 'null', 'undefined', 'unknown')\n *\n * @example\n * detectType(\"hello\") // → \"string\"\n * detectType(42) // → \"number\"\n * detectType(true) // → \"boolean\"\n * detectType([1, 2, 3]) // → \"array\"\n * detectType({}) // → \"object\"\n * detectType(new Date()) // → \"date\"\n * detectType(null) // → \"null\"\n */\n const detectType = (value) => {\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (typeof value === \"boolean\") return \"boolean\";\n if (typeof value === \"number\") return \"number\";\n if (typeof value === \"string\") return \"string\";\n if (typeof value === \"function\") return \"function\";\n if (value instanceof Date) return \"date\";\n if (value instanceof Map) return \"map\";\n if (value instanceof Set) return \"set\";\n if (Array.isArray(value)) return \"array\";\n if (typeof value === \"object\") return \"object\";\n return \"unknown\";\n };\n\n /**\n * Parses a prop value with automatic type detection\n * @private\n * @param {any} value - The value to parse\n * @returns {any} The parsed value with appropriate type\n *\n * @description\n * This function automatically detects and parses different data types from string values:\n * - Special strings: \"true\" → true, \"false\" → false, \"null\" → null, \"undefined\" → undefined\n * - JSON objects/arrays: '{\"key\": \"value\"}' → {key: \"value\"}, '[1, 2, 3]' → [1, 2, 3]\n * - Boolean-like strings: \"1\" → true, \"0\" → false, \"\" → true\n * - Numeric strings: \"42\" → 42, \"3.14\" → 3.14\n * - Date strings: \"2023-01-01T00:00:00.000Z\" → Date object\n * - Other strings: returned as-is\n *\n * @example\n * parsePropValue(\"true\") // → true\n * parsePropValue(\"42\") // → 42\n * parsePropValue('{\"key\": \"val\"}') // → {key: \"val\"}\n * parsePropValue('[1, 2, 3]') // → [1, 2, 3]\n * parsePropValue(\"hello\") // → \"hello\"\n */\n const parsePropValue = (value) => {\n try {\n // Handle non-string values - return as-is\n if (typeof value !== \"string\") {\n return value;\n }\n\n // Handle special string patterns first\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n if (value === \"null\") return null;\n if (value === \"undefined\") return undefined;\n\n // Try to parse as JSON (for objects and arrays)\n // This handles complex data structures like objects and arrays\n if (value.startsWith(\"{\") || value.startsWith(\"[\")) {\n try {\n return JSON.parse(value);\n } catch (e) {\n // Not valid JSON, throw error to trigger error handler\n throw new Error(`Invalid JSON: ${value}`);\n }\n }\n\n // Handle boolean-like strings (including \"1\" and \"0\")\n // These are common in HTML attributes and should be treated as booleans\n if (value === \"1\") return true;\n if (value === \"0\") return false;\n if (value === \"\") return true; // Empty string is truthy in HTML attributes\n\n // Handle numeric strings (after boolean check to avoid conflicts)\n // This ensures \"0\" is treated as boolean false, not number 0\n if (!isNaN(value) && value !== \"\" && !isNaN(parseFloat(value))) {\n return Number(value);\n }\n\n // Handle date strings (ISO format)\n // Recognizes standard ISO date format and converts to Date object\n if (value.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/)) {\n const date = new Date(value);\n if (!isNaN(date.getTime())) {\n return date;\n }\n }\n\n // Return as string if no other parsing applies\n // This is the fallback for regular text strings\n return value;\n } catch (error) {\n // Call error handler if provided\n if (onError) {\n onError(error, value);\n }\n // Fallback to original value to prevent breaking the application\n return value;\n }\n };\n\n /**\n * Enhanced props extraction with automatic type detection\n * @private\n * @param {HTMLElement} element - The DOM element to extract props from\n * @returns {Object} Object containing parsed props with appropriate types\n *\n * @description\n * Extracts props from DOM element attributes that start with \":\" and automatically\n * parses them to their appropriate types. Removes the attributes from the element\n * after extraction.\n *\n * @example\n * // HTML: <div :name=\"John\" :age=\"30\" :active=\"true\" :data='{\"key\": \"value\"}'></div>\n * const props = extractProps(element);\n * // Result: { name: \"John\", age: 30, active: true, data: {key: \"value\"} }\n */\n const extractProps = (element) => {\n const props = {};\n const attrs = element.attributes;\n\n // Iterate through attributes in reverse order to handle removal correctly\n for (let i = attrs.length - 1; i >= 0; i--) {\n const attr = attrs[i];\n // Only process attributes that start with \":\" (prop attributes)\n if (attr.name.startsWith(\":\")) {\n const propName = attr.name.slice(1); // Remove the \":\" prefix\n // Parse the value if auto-parsing is enabled, otherwise use as-is\n const parsedValue = enableAutoParsing\n ? parsePropValue(attr.value)\n : attr.value;\n props[propName] = parsedValue;\n // Remove the attribute from the DOM element after extraction\n element.removeAttribute(attr.name);\n }\n }\n\n return props;\n };\n\n /**\n * Creates reactive props using Eleva's signal system\n * @private\n * @param {Object} props - The props object to make reactive\n * @returns {Object} Object containing reactive props (Eleva signals)\n *\n * @description\n * Converts regular prop values into Eleva signals for reactive updates.\n * If a value is already a signal, it's passed through unchanged.\n *\n * @example\n * const props = { name: \"John\", age: 30, active: true };\n * const reactiveProps = createReactiveProps(props);\n * // Result: {\n * // name: Signal(\"John\"),\n * // age: Signal(30),\n * // active: Signal(true)\n * // }\n */\n const createReactiveProps = (props) => {\n const reactiveProps = {};\n\n // Convert each prop value to a reactive signal\n Object.entries(props).forEach(([key, value]) => {\n // Check if value is already a signal (has 'value' and 'watch' properties)\n if (\n value &&\n typeof value === \"object\" &&\n \"value\" in value &&\n \"watch\" in value\n ) {\n // Value is already a signal, use it as-is\n reactiveProps[key] = value;\n } else {\n // Create new signal for the prop value to make it reactive\n reactiveProps[key] = new eleva.signal(value);\n }\n });\n\n return reactiveProps;\n };\n\n // Override Eleva's internal _extractProps method with our enhanced version\n eleva._extractProps = extractProps;\n\n // Override Eleva's mount method to apply enhanced prop handling\n const originalMount = eleva.mount;\n eleva.mount = async (container, compName, props = {}) => {\n // Create reactive props if reactivity is enabled\n const enhancedProps = enableReactivity\n ? createReactiveProps(props)\n : props;\n\n // Call the original mount method with enhanced props\n return await originalMount.call(\n eleva,\n container,\n compName,\n enhancedProps\n );\n };\n\n /**\n * Expose utility methods on the Eleva instance\n * @namespace eleva.props\n */\n eleva.props = {\n /**\n * Parse a single value with automatic type detection\n * @param {any} value - The value to parse\n * @returns {any} The parsed value with appropriate type\n *\n * @example\n * app.props.parse(\"42\") // → 42\n * app.props.parse(\"true\") // → true\n * app.props.parse('{\"key\": \"val\"}') // → {key: \"val\"}\n */\n parse: (value) => {\n // Return value as-is if auto parsing is disabled\n if (!enableAutoParsing) {\n return value;\n }\n // Use our enhanced parsing function\n return parsePropValue(value);\n },\n\n /**\n * Detect the type of a value\n * @param {any} value - The value to detect type for\n * @returns {string} The detected type\n *\n * @example\n * app.props.detectType(\"hello\") // → \"string\"\n * app.props.detectType(42) // → \"number\"\n * app.props.detectType([1, 2, 3]) // → \"array\"\n */\n detectType,\n };\n\n // Store original methods for uninstall\n eleva._originalExtractProps = eleva._extractProps;\n eleva._originalMount = originalMount;\n },\n\n /**\n * Uninstalls the plugin from the Eleva instance\n *\n * @param {Object} eleva - The Eleva instance\n *\n * @description\n * Restores the original Eleva methods and removes all plugin-specific\n * functionality. This method should be called when the plugin is no\n * longer needed.\n *\n * @example\n * // Uninstall the plugin\n * PropsPlugin.uninstall(app);\n */\n uninstall(eleva) {\n // Restore original _extractProps method\n if (eleva._originalExtractProps) {\n eleva._extractProps = eleva._originalExtractProps;\n delete eleva._originalExtractProps;\n }\n\n // Restore original mount method\n if (eleva._originalMount) {\n eleva.mount = eleva._originalMount;\n delete eleva._originalMount;\n }\n\n // Remove plugin utility methods\n if (eleva.props) {\n delete eleva.props;\n }\n },\n};\n"],"names":["PropsPlugin","name","version","description","install","eleva","options","enableAutoParsing","enableReactivity","onError","detectType","value","undefined","Date","Map","Set","Array","isArray","parsePropValue","startsWith","JSON","parse","e","Error","isNaN","parseFloat","Number","match","date","getTime","error","extractProps","element","props","attrs","attributes","i","length","attr","propName","slice","parsedValue","removeAttribute","createReactiveProps","reactiveProps","Object","entries","forEach","key","signal","_extractProps","originalMount","mount","container","compName","enhancedProps","call","_originalExtractProps","_originalMount","uninstall"],"mappings":"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"}
1
+ {"version":3,"file":"props.umd.js","sources":["../../src/modules/TemplateEngine.js","../../src/plugins/Props.js"],"sourcesContent":["\"use strict\";\n\n/**\n * @class 🔒 TemplateEngine\n * @classdesc A secure template engine that handles interpolation and dynamic attribute parsing.\n * Provides a safe way to evaluate expressions in templates while preventing XSS attacks.\n * All methods are static and can be called directly on the class.\n *\n * @example\n * const template = \"Hello, {{name}}!\";\n * const data = { name: \"World\" };\n * const result = TemplateEngine.parse(template, data); // Returns: \"Hello, World!\"\n */\nexport class TemplateEngine {\n /**\n * @private {RegExp} Regular expression for matching template expressions in the format {{ expression }}\n * @type {RegExp}\n */\n static expressionPattern = /\\{\\{\\s*(.*?)\\s*\\}\\}/g;\n\n /**\n * Parses a template string, replacing expressions with their evaluated values.\n * Expressions are evaluated in the provided data context.\n *\n * @public\n * @static\n * @param {string} template - The template string to parse.\n * @param {Record<string, unknown>} data - The data context for evaluating expressions.\n * @returns {string} The parsed template with expressions replaced by their values.\n * @example\n * const result = TemplateEngine.parse(\"{{user.name}} is {{user.age}} years old\", {\n * user: { name: \"John\", age: 30 }\n * }); // Returns: \"John is 30 years old\"\n */\n static parse(template, data) {\n if (typeof template !== \"string\") return template;\n return template.replace(this.expressionPattern, (_, expression) =>\n this.evaluate(expression, data)\n );\n }\n\n /**\n * Evaluates an expression in the context of the provided data object.\n * Note: This does not provide a true sandbox and evaluated expressions may access global scope.\n * The use of the `with` statement is necessary for expression evaluation but has security implications.\n * Expressions should be carefully validated before evaluation.\n *\n * @public\n * @static\n * @param {string} expression - The expression to evaluate.\n * @param {Record<string, unknown>} data - The data context for evaluation.\n * @returns {unknown} The result of the evaluation, or an empty string if evaluation fails.\n * @example\n * const result = TemplateEngine.evaluate(\"user.name\", { user: { name: \"John\" } }); // Returns: \"John\"\n * const age = TemplateEngine.evaluate(\"user.age\", { user: { age: 30 } }); // Returns: 30\n */\n static evaluate(expression, data) {\n if (typeof expression !== \"string\") return expression;\n try {\n return new Function(\"data\", `with(data) { return ${expression}; }`)(data);\n } catch {\n return \"\";\n }\n }\n}\n","\"use strict\";\n\nimport { TemplateEngine } from \"../modules/TemplateEngine.js\";\n\n/**\n * @class 🎯 PropsPlugin\n * @classdesc A plugin that extends Eleva's props data handling to support any type of data structure\n * with automatic type detection, parsing, and reactive prop updates. This plugin enables seamless\n * passing of complex data types from parent to child components without manual parsing.\n *\n * Core Features:\n * - Automatic type detection and parsing (strings, numbers, booleans, objects, arrays, dates, etc.)\n * - Support for complex data structures including nested objects and arrays\n * - Reactive props that automatically update when parent data changes\n * - Comprehensive error handling with custom error callbacks\n * - Simple configuration with minimal setup required\n *\n * @example\n * // Install the plugin\n * const app = new Eleva(\"myApp\");\n * app.use(PropsPlugin, {\n * enableAutoParsing: true,\n * enableReactivity: true,\n * onError: (error, value) => {\n * console.error('Props parsing error:', error, value);\n * }\n * });\n *\n * // Use complex props in components\n * app.component(\"UserCard\", {\n * template: (ctx) => `\n * <div class=\"user-info-container\"\n * :user='${JSON.stringify(ctx.user.value)}'\n * :permissions='${JSON.stringify(ctx.permissions.value)}'\n * :settings='${JSON.stringify(ctx.settings.value)}'>\n * </div>\n * `,\n * children: {\n * '.user-info-container': 'UserInfo'\n * }\n * });\n *\n * app.component(\"UserInfo\", {\n * setup({ props }) {\n * return {\n * user: props.user, // Automatically parsed object\n * permissions: props.permissions, // Automatically parsed array\n * settings: props.settings // Automatically parsed object\n * };\n * }\n * });\n */\nexport const PropsPlugin = {\n /**\n * Unique identifier for the plugin\n * @type {string}\n */\n name: \"props\",\n\n /**\n * Plugin version\n * @type {string}\n */\n version: \"1.0.0-rc.2\",\n\n /**\n * Plugin description\n * @type {string}\n */\n description:\n \"Advanced props data handling for complex data structures with automatic type detection and reactivity\",\n\n /**\n * Installs the plugin into the Eleva instance\n *\n * @param {Object} eleva - The Eleva instance\n * @param {Object} options - Plugin configuration options\n * @param {boolean} [options.enableAutoParsing=true] - Enable automatic type detection and parsing\n * @param {boolean} [options.enableReactivity=true] - Enable reactive prop updates using Eleva's signal system\n * @param {Function} [options.onError=null] - Error handler function called when parsing fails\n *\n * @example\n * // Basic installation\n * app.use(PropsPlugin);\n *\n * // Installation with custom options\n * app.use(PropsPlugin, {\n * enableAutoParsing: true,\n * enableReactivity: false,\n * onError: (error, value) => {\n * console.error('Props parsing error:', error, value);\n * }\n * });\n */\n install(eleva, options = {}) {\n const {\n enableAutoParsing = true,\n enableReactivity = true,\n onError = null,\n } = options;\n\n /**\n * Detects the type of a given value\n * @private\n * @param {any} value - The value to detect type for\n * @returns {string} The detected type ('string', 'number', 'boolean', 'object', 'array', 'date', 'map', 'set', 'function', 'null', 'undefined', 'unknown')\n *\n * @example\n * detectType(\"hello\") // → \"string\"\n * detectType(42) // → \"number\"\n * detectType(true) // → \"boolean\"\n * detectType([1, 2, 3]) // → \"array\"\n * detectType({}) // → \"object\"\n * detectType(new Date()) // → \"date\"\n * detectType(null) // → \"null\"\n */\n const detectType = (value) => {\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (typeof value === \"boolean\") return \"boolean\";\n if (typeof value === \"number\") return \"number\";\n if (typeof value === \"string\") return \"string\";\n if (typeof value === \"function\") return \"function\";\n if (value instanceof Date) return \"date\";\n if (value instanceof Map) return \"map\";\n if (value instanceof Set) return \"set\";\n if (Array.isArray(value)) return \"array\";\n if (typeof value === \"object\") return \"object\";\n return \"unknown\";\n };\n\n /**\n * Parses a prop value with automatic type detection\n * @private\n * @param {any} value - The value to parse\n * @returns {any} The parsed value with appropriate type\n *\n * @description\n * This function automatically detects and parses different data types from string values:\n * - Special strings: \"true\" → true, \"false\" → false, \"null\" → null, \"undefined\" → undefined\n * - JSON objects/arrays: '{\"key\": \"value\"}' → {key: \"value\"}, '[1, 2, 3]' → [1, 2, 3]\n * - Boolean-like strings: \"1\" → true, \"0\" → false, \"\" → true\n * - Numeric strings: \"42\" → 42, \"3.14\" → 3.14\n * - Date strings: \"2023-01-01T00:00:00.000Z\" → Date object\n * - Other strings: returned as-is\n *\n * @example\n * parsePropValue(\"true\") // → true\n * parsePropValue(\"42\") // → 42\n * parsePropValue('{\"key\": \"val\"}') // → {key: \"val\"}\n * parsePropValue('[1, 2, 3]') // → [1, 2, 3]\n * parsePropValue(\"hello\") // → \"hello\"\n */\n const parsePropValue = (value) => {\n try {\n // Handle non-string values - return as-is\n if (typeof value !== \"string\") {\n return value;\n }\n\n // Handle special string patterns first\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n if (value === \"null\") return null;\n if (value === \"undefined\") return undefined;\n\n // Try to parse as JSON (for objects and arrays)\n // This handles complex data structures like objects and arrays\n if (value.startsWith(\"{\") || value.startsWith(\"[\")) {\n try {\n return JSON.parse(value);\n } catch (e) {\n // Not valid JSON, throw error to trigger error handler\n throw new Error(`Invalid JSON: ${value}`);\n }\n }\n\n // Handle boolean-like strings (including \"1\" and \"0\")\n // These are common in HTML attributes and should be treated as booleans\n if (value === \"1\") return true;\n if (value === \"0\") return false;\n if (value === \"\") return true; // Empty string is truthy in HTML attributes\n\n // Handle numeric strings (after boolean check to avoid conflicts)\n // This ensures \"0\" is treated as boolean false, not number 0\n if (!isNaN(value) && value !== \"\" && !isNaN(parseFloat(value))) {\n return Number(value);\n }\n\n // Handle date strings (ISO format)\n // Recognizes standard ISO date format and converts to Date object\n if (value.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/)) {\n const date = new Date(value);\n if (!isNaN(date.getTime())) {\n return date;\n }\n }\n\n // Return as string if no other parsing applies\n // This is the fallback for regular text strings\n return value;\n } catch (error) {\n // Call error handler if provided\n if (onError) {\n onError(error, value);\n }\n // Fallback to original value to prevent breaking the application\n return value;\n }\n };\n\n /**\n * Enhanced props extraction with automatic type detection\n * @private\n * @param {HTMLElement} element - The DOM element to extract props from\n * @returns {Object} Object containing parsed props with appropriate types\n *\n * @description\n * Extracts props from DOM element attributes that start with \":\" and automatically\n * parses them to their appropriate types. Removes the attributes from the element\n * after extraction.\n *\n * @example\n * // HTML: <div :name=\"John\" :age=\"30\" :active=\"true\" :data='{\"key\": \"value\"}'></div>\n * const props = extractProps(element);\n * // Result: { name: \"John\", age: 30, active: true, data: {key: \"value\"} }\n */\n const extractProps = (element) => {\n const props = {};\n const attrs = element.attributes;\n\n // Iterate through attributes in reverse order to handle removal correctly\n for (let i = attrs.length - 1; i >= 0; i--) {\n const attr = attrs[i];\n // Only process attributes that start with \":\" (prop attributes)\n if (attr.name.startsWith(\":\")) {\n const propName = attr.name.slice(1); // Remove the \":\" prefix\n // Parse the value if auto-parsing is enabled, otherwise use as-is\n const parsedValue = enableAutoParsing\n ? parsePropValue(attr.value)\n : attr.value;\n props[propName] = parsedValue;\n // Remove the attribute from the DOM element after extraction\n element.removeAttribute(attr.name);\n }\n }\n\n return props;\n };\n\n /**\n * Creates reactive props using Eleva's signal system\n * @private\n * @param {Object} props - The props object to make reactive\n * @returns {Object} Object containing reactive props (Eleva signals)\n *\n * @description\n * Converts regular prop values into Eleva signals for reactive updates.\n * If a value is already a signal, it's passed through unchanged.\n *\n * @example\n * const props = { name: \"John\", age: 30, active: true };\n * const reactiveProps = createReactiveProps(props);\n * // Result: {\n * // name: Signal(\"John\"),\n * // age: Signal(30),\n * // active: Signal(true)\n * // }\n */\n const createReactiveProps = (props) => {\n const reactiveProps = {};\n\n // Convert each prop value to a reactive signal\n Object.entries(props).forEach(([key, value]) => {\n // Check if value is already a signal (has 'value' and 'watch' properties)\n if (\n value &&\n typeof value === \"object\" &&\n \"value\" in value &&\n \"watch\" in value\n ) {\n // Value is already a signal, use it as-is\n reactiveProps[key] = value;\n } else {\n // Create new signal for the prop value to make it reactive\n reactiveProps[key] = new eleva.signal(value);\n }\n });\n\n return reactiveProps;\n };\n\n // Override Eleva's internal _extractProps method with our enhanced version\n eleva._extractProps = extractProps;\n\n // Override Eleva's mount method to apply enhanced prop handling\n const originalMount = eleva.mount;\n eleva.mount = async (container, compName, props = {}) => {\n // Create reactive props if reactivity is enabled\n const enhancedProps = enableReactivity\n ? createReactiveProps(props)\n : props;\n\n // Call the original mount method with enhanced props\n return await originalMount.call(\n eleva,\n container,\n compName,\n enhancedProps\n );\n };\n\n // Override Eleva's _mountComponents method to enable signal reference passing\n const originalMountComponents = eleva._mountComponents;\n\n // Cache to store parent contexts by container element\n const parentContextCache = new WeakMap();\n // Store child instances that need signal linking\n const pendingSignalLinks = new Set();\n\n eleva._mountComponents = async (container, children, childInstances) => {\n for (const [selector, component] of Object.entries(children)) {\n if (!selector) continue;\n for (const el of container.querySelectorAll(selector)) {\n if (!(el instanceof HTMLElement)) continue;\n\n // Extract props from DOM attributes\n const extractedProps = eleva._extractProps(el);\n\n // Get parent context to check for signal references\n let enhancedProps = extractedProps;\n\n // Try to find parent context by looking up the DOM tree\n let parentContext = parentContextCache.get(container);\n if (!parentContext) {\n let currentElement = container;\n while (currentElement && !parentContext) {\n if (\n currentElement._eleva_instance &&\n currentElement._eleva_instance.data\n ) {\n parentContext = currentElement._eleva_instance.data;\n // Cache the parent context for future use\n parentContextCache.set(container, parentContext);\n break;\n }\n currentElement = currentElement.parentElement;\n }\n }\n\n if (enableReactivity && parentContext) {\n const signalProps = {};\n\n // Check each extracted prop to see if there's a matching signal in parent context\n Object.keys(extractedProps).forEach((propName) => {\n if (\n parentContext[propName] &&\n parentContext[propName] instanceof eleva.signal\n ) {\n // Found a signal in parent context with the same name as the prop\n // Pass the signal reference instead of creating a new one\n signalProps[propName] = parentContext[propName];\n }\n });\n\n // Merge signal props with regular props (signal props take precedence)\n enhancedProps = {\n ...extractedProps,\n ...signalProps,\n };\n }\n\n // Create reactive props for non-signal props only\n let finalProps = enhancedProps;\n if (enableReactivity) {\n // Only create reactive props for values that aren't already signals\n const nonSignalProps = {};\n Object.entries(enhancedProps).forEach(([key, value]) => {\n if (\n !(\n value &&\n typeof value === \"object\" &&\n \"value\" in value &&\n \"watch\" in value\n )\n ) {\n // This is not a signal, create a reactive prop for it\n nonSignalProps[key] = value;\n }\n });\n\n // Create reactive props only for non-signal values\n const reactiveNonSignalProps = createReactiveProps(nonSignalProps);\n\n // Merge signal props with reactive non-signal props\n finalProps = {\n ...reactiveNonSignalProps,\n ...enhancedProps, // Signal props take precedence\n };\n }\n\n /** @type {MountResult} */\n const instance = await eleva.mount(el, component, finalProps);\n if (instance && !childInstances.includes(instance)) {\n childInstances.push(instance);\n\n // If we have extracted props but no parent context yet, mark for later signal linking\n if (\n enableReactivity &&\n Object.keys(extractedProps).length > 0 &&\n !parentContext\n ) {\n pendingSignalLinks.add({\n instance,\n extractedProps,\n container,\n component,\n });\n }\n }\n }\n }\n\n // After mounting all children, try to link signals for pending instances\n if (enableReactivity && pendingSignalLinks.size > 0) {\n for (const pending of pendingSignalLinks) {\n const { instance, extractedProps, container, component } = pending;\n\n // Try to find parent context again\n let parentContext = parentContextCache.get(container);\n if (!parentContext) {\n let currentElement = container;\n while (currentElement && !parentContext) {\n if (\n currentElement._eleva_instance &&\n currentElement._eleva_instance.data\n ) {\n parentContext = currentElement._eleva_instance.data;\n parentContextCache.set(container, parentContext);\n break;\n }\n currentElement = currentElement.parentElement;\n }\n }\n\n if (parentContext) {\n const signalProps = {};\n\n // Check each extracted prop to see if there's a matching signal in parent context\n Object.keys(extractedProps).forEach((propName) => {\n if (\n parentContext[propName] &&\n parentContext[propName] instanceof eleva.signal\n ) {\n signalProps[propName] = parentContext[propName];\n }\n });\n\n // Update the child instance's data with signal references\n if (Object.keys(signalProps).length > 0) {\n Object.assign(instance.data, signalProps);\n\n // Set up signal watchers for the newly linked signals\n Object.keys(signalProps).forEach((propName) => {\n const signal = signalProps[propName];\n if (signal && typeof signal.watch === \"function\") {\n signal.watch((newValue) => {\n // Trigger a re-render of the child component when the signal changes\n const childComponent =\n eleva._components.get(component) || component;\n if (childComponent && childComponent.template) {\n const templateResult =\n typeof childComponent.template === \"function\"\n ? childComponent.template(instance.data)\n : childComponent.template;\n const newHtml = TemplateEngine.parse(\n templateResult,\n instance.data\n );\n eleva.renderer.patchDOM(instance.container, newHtml);\n }\n });\n }\n });\n\n // Initial re-render to show the correct signal values\n const childComponent =\n eleva._components.get(component) || component;\n if (childComponent && childComponent.template) {\n const templateResult =\n typeof childComponent.template === \"function\"\n ? childComponent.template(instance.data)\n : childComponent.template;\n const newHtml = TemplateEngine.parse(\n templateResult,\n instance.data\n );\n eleva.renderer.patchDOM(instance.container, newHtml);\n }\n }\n\n // Remove from pending list\n pendingSignalLinks.delete(pending);\n }\n }\n }\n };\n\n /**\n * Expose utility methods on the Eleva instance\n * @namespace eleva.props\n */\n eleva.props = {\n /**\n * Parse a single value with automatic type detection\n * @param {any} value - The value to parse\n * @returns {any} The parsed value with appropriate type\n *\n * @example\n * app.props.parse(\"42\") // → 42\n * app.props.parse(\"true\") // → true\n * app.props.parse('{\"key\": \"val\"}') // → {key: \"val\"}\n */\n parse: (value) => {\n // Return value as-is if auto parsing is disabled\n if (!enableAutoParsing) {\n return value;\n }\n // Use our enhanced parsing function\n return parsePropValue(value);\n },\n\n /**\n * Detect the type of a value\n * @param {any} value - The value to detect type for\n * @returns {string} The detected type\n *\n * @example\n * app.props.detectType(\"hello\") // → \"string\"\n * app.props.detectType(42) // → \"number\"\n * app.props.detectType([1, 2, 3]) // → \"array\"\n */\n detectType,\n };\n\n // Store original methods for uninstall\n eleva._originalExtractProps = eleva._extractProps;\n eleva._originalMount = originalMount;\n eleva._originalMountComponents = originalMountComponents;\n },\n\n /**\n * Uninstalls the plugin from the Eleva instance\n *\n * @param {Object} eleva - The Eleva instance\n *\n * @description\n * Restores the original Eleva methods and removes all plugin-specific\n * functionality. This method should be called when the plugin is no\n * longer needed.\n *\n * @example\n * // Uninstall the plugin\n * PropsPlugin.uninstall(app);\n */\n uninstall(eleva) {\n // Restore original _extractProps method\n if (eleva._originalExtractProps) {\n eleva._extractProps = eleva._originalExtractProps;\n delete eleva._originalExtractProps;\n }\n\n // Restore original mount method\n if (eleva._originalMount) {\n eleva.mount = eleva._originalMount;\n delete eleva._originalMount;\n }\n\n // Restore original _mountComponents method\n if (eleva._originalMountComponents) {\n eleva._mountComponents = eleva._originalMountComponents;\n delete eleva._originalMountComponents;\n }\n\n // Remove plugin utility methods\n if (eleva.props) {\n delete eleva.props;\n }\n },\n};\n"],"names":["TemplateEngine","expressionPattern","parse","template","data","replace","_","expression","evaluate","Function","PropsPlugin","name","version","description","install","eleva","options","enableAutoParsing","enableReactivity","onError","detectType","value","undefined","Date","Map","Set","Array","isArray","parsePropValue","startsWith","JSON","e","Error","isNaN","parseFloat","Number","match","date","getTime","error","extractProps","element","props","attrs","attributes","i","length","attr","propName","slice","parsedValue","removeAttribute","createReactiveProps","reactiveProps","Object","entries","forEach","key","signal","_extractProps","originalMount","mount","container","compName","enhancedProps","call","originalMountComponents","_mountComponents","parentContextCache","WeakMap","pendingSignalLinks","children","childInstances","selector","component","el","querySelectorAll","HTMLElement","extractedProps","parentContext","get","currentElement","_eleva_instance","set","parentElement","signalProps","keys","finalProps","nonSignalProps","reactiveNonSignalProps","instance","includes","push","add","size","pending","assign","watch","newValue","childComponent","_components","templateResult","newHtml","renderer","patchDOM","delete","_originalExtractProps","_originalMount","_originalMountComponents","uninstall"],"mappings":";;;;;;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACO,MAAMA,cAAc,CAAC;EAC1B;EACF;EACA;EACA;IACE,OAAOC,iBAAiB,GAAG,sBAAsB;;EAEjD;EACF;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACE,EAAA,OAAOC,KAAKA,CAACC,QAAQ,EAAEC,IAAI,EAAE;EAC3B,IAAA,IAAI,OAAOD,QAAQ,KAAK,QAAQ,EAAE,OAAOA,QAAQ;MACjD,OAAOA,QAAQ,CAACE,OAAO,CAAC,IAAI,CAACJ,iBAAiB,EAAE,CAACK,CAAC,EAAEC,UAAU,KAC5D,IAAI,CAACC,QAAQ,CAACD,UAAU,EAAEH,IAAI,CAChC,CAAC;EACH,EAAA;;EAEA;EACF;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACE,EAAA,OAAOI,QAAQA,CAACD,UAAU,EAAEH,IAAI,EAAE;EAChC,IAAA,IAAI,OAAOG,UAAU,KAAK,QAAQ,EAAE,OAAOA,UAAU;MACrD,IAAI;QACF,OAAO,IAAIE,QAAQ,CAAC,MAAM,EAAE,CAAA,oBAAA,EAAuBF,UAAU,CAAA,GAAA,CAAK,CAAC,CAACH,IAAI,CAAC;EAC3E,IAAA,CAAC,CAAC,MAAM;EACN,MAAA,OAAO,EAAE;EACX,IAAA;EACF,EAAA;EACF;;EC5DA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACO,QAAMM,WAAW,GAAG;EACzB;EACF;EACA;EACA;EACEC,EAAAA,IAAI,EAAE,OAAO;EAEb;EACF;EACA;EACA;EACEC,EAAAA,OAAO,EAAE,YAAY;EAErB;EACF;EACA;EACA;EACEC,EAAAA,WAA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"}
@@ -1,3 +1,3 @@
1
- /*! Eleva Props Plugin v1.0.0-rc.1 | MIT License | https://elevajs.com */
2
- var t,e;t=this,e=function(t){"use strict";t.PropsPlugin={name:"props",version:"1.0.0-rc.1",description:"Advanced props data handling for complex data structures with automatic type detection and reactivity",install(t,e={}){const{enableAutoParsing:n=!0,enableReactivity:r=!0,onError:o=null}=e,i=t=>{try{if("string"!=typeof t)return t;if("true"===t)return!0;if("false"===t)return!1;if("null"===t)return null;if("undefined"===t)return;if(t.startsWith("{")||t.startsWith("["))try{return JSON.parse(t)}catch(e){throw new Error(`Invalid JSON: ${t}`)}if("1"===t)return!0;if("0"===t)return!1;if(""===t)return!0;if(!isNaN(t)&&""!==t&&!isNaN(parseFloat(t)))return Number(t);if(t.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)){const e=new Date(t);if(!isNaN(e.getTime()))return e}return t}catch(e){return o&&o(e,t),t}};t._extractProps=t=>{const e={},r=t.attributes;for(let o=r.length-1;o>=0;o--){const a=r[o];if(a.name.startsWith(":")){const r=a.name.slice(1),o=n?i(a.value):a.value;e[r]=o,t.removeAttribute(a.name)}}return e};const a=t.mount;t.mount=async(e,n,o={})=>{const i=r?(e=>{const n={};return Object.entries(e).forEach(([e,r])=>{n[e]=r&&"object"==typeof r&&"value"in r&&"watch"in r?r:new t.signal(r)}),n})(o):o;return await a.call(t,e,n,i)},t.props={parse:t=>n?i(t):t,detectType:t=>null===t?"null":void 0===t?"undefined":"boolean"==typeof t?"boolean":"number"==typeof t?"number":"string"==typeof t?"string":"function"==typeof t?"function":t instanceof Date?"date":t instanceof Map?"map":t instanceof Set?"set":Array.isArray(t)?"array":"object"==typeof t?"object":"unknown"},t._originalExtractProps=t._extractProps,t._originalMount=a},uninstall(t){t._originalExtractProps&&(t._extractProps=t._originalExtractProps,delete t._originalExtractProps),t._originalMount&&(t.mount=t._originalMount,delete t._originalMount),t.props&&delete t.props}}},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ElevaPropsPlugin={});
1
+ /*! Eleva Props Plugin v1.0.0-rc.2 | MIT License | https://elevajs.com */
2
+ var t,e;t=this,e=function(t){"use strict";class e{static expressionPattern=/\{\{\s*(.*?)\s*\}\}/g;static parse(t,e){return"string"!=typeof t?t:t.replace(this.expressionPattern,(t,n)=>this.evaluate(n,e))}static evaluate(t,e){if("string"!=typeof t)return t;try{return new Function("data",`with(data) { return ${t}; }`)(e)}catch{return""}}}t.PropsPlugin={name:"props",version:"1.0.0-rc.2",description:"Advanced props data handling for complex data structures with automatic type detection and reactivity",install(t,n={}){const{enableAutoParsing:a=!0,enableReactivity:o=!0,onError:r=null}=n,i=t=>{try{if("string"!=typeof t)return t;if("true"===t)return!0;if("false"===t)return!1;if("null"===t)return null;if("undefined"===t)return;if(t.startsWith("{")||t.startsWith("["))try{return JSON.parse(t)}catch(e){throw new Error(`Invalid JSON: ${t}`)}if("1"===t)return!0;if("0"===t)return!1;if(""===t)return!0;if(!isNaN(t)&&""!==t&&!isNaN(parseFloat(t)))return Number(t);if(t.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)){const e=new Date(t);if(!isNaN(e.getTime()))return e}return t}catch(e){return r&&r(e,t),t}},s=e=>{const n={};return Object.entries(e).forEach(([e,a])=>{n[e]=a&&"object"==typeof a&&"value"in a&&"watch"in a?a:new t.signal(a)}),n};t._extractProps=t=>{const e={},n=t.attributes;for(let o=n.length-1;o>=0;o--){const r=n[o];if(r.name.startsWith(":")){const n=r.name.slice(1),o=a?i(r.value):r.value;e[n]=o,t.removeAttribute(r.name)}}return e};const c=t.mount;t.mount=async(e,n,a={})=>{const r=o?s(a):a;return await c.call(t,e,n,r)};const l=t._mountComponents,p=new WeakMap,f=new Set;t._mountComponents=async(n,a,r)=>{for(const[e,i]of Object.entries(a))if(e)for(const a of n.querySelectorAll(e)){if(!(a instanceof HTMLElement))continue;const e=t._extractProps(a);let c=e,l=p.get(n);if(!l){let t=n;for(;t&&!l;){if(t._eleva_instance&&t._eleva_instance.data){l=t._eleva_instance.data,p.set(n,l);break}t=t.parentElement}}if(o&&l){const n={};Object.keys(e).forEach(e=>{l[e]&&l[e]instanceof t.signal&&(n[e]=l[e])}),c={...e,...n}}let u=c;if(o){const t={};Object.entries(c).forEach(([e,n])=>{n&&"object"==typeof n&&"value"in n&&"watch"in n||(t[e]=n)}),u={...s(t),...c}}const d=await t.mount(a,i,u);d&&!r.includes(d)&&(r.push(d),o&&Object.keys(e).length>0&&!l&&f.add({instance:d,extractedProps:e,container:n,component:i}))}if(o&&f.size>0)for(const n of f){const{instance:a,extractedProps:o,container:r,component:i}=n;let s=p.get(r);if(!s){let t=r;for(;t&&!s;){if(t._eleva_instance&&t._eleva_instance.data){s=t._eleva_instance.data,p.set(r,s);break}t=t.parentElement}}if(s){const r={};if(Object.keys(o).forEach(e=>{s[e]&&s[e]instanceof t.signal&&(r[e]=s[e])}),Object.keys(r).length>0){Object.assign(a.data,r),Object.keys(r).forEach(n=>{const o=r[n];o&&"function"==typeof o.watch&&o.watch(()=>{const n=t._components.get(i)||i;if(n&&n.template){const o="function"==typeof n.template?n.template(a.data):n.template,r=e.parse(o,a.data);t.renderer.patchDOM(a.container,r)}})});const n=t._components.get(i)||i;if(n&&n.template){const o="function"==typeof n.template?n.template(a.data):n.template,r=e.parse(o,a.data);t.renderer.patchDOM(a.container,r)}}f.delete(n)}}},t.props={parse:t=>a?i(t):t,detectType:t=>null===t?"null":void 0===t?"undefined":"boolean"==typeof t?"boolean":"number"==typeof t?"number":"string"==typeof t?"string":"function"==typeof t?"function":t instanceof Date?"date":t instanceof Map?"map":t instanceof Set?"set":Array.isArray(t)?"array":"object"==typeof t?"object":"unknown"},t._originalExtractProps=t._extractProps,t._originalMount=c,t._originalMountComponents=l},uninstall(t){t._originalExtractProps&&(t._extractProps=t._originalExtractProps,delete t._originalExtractProps),t._originalMount&&(t.mount=t._originalMount,delete t._originalMount),t._originalMountComponents&&(t._mountComponents=t._originalMountComponents,delete t._originalMountComponents),t.props&&delete t.props}}},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ElevaPropsPlugin={});
3
3
  //# sourceMappingURL=props.umd.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"props.umd.min.js","sources":["../../src/plugins/Props.js"],"sourcesContent":["\"use strict\";\n\n/**\n * @class 🎯 PropsPlugin\n * @classdesc A plugin that extends Eleva's props data handling to support any type of data structure\n * with automatic type detection, parsing, and reactive prop updates. This plugin enables seamless\n * passing of complex data types from parent to child components without manual parsing.\n *\n * Core Features:\n * - Automatic type detection and parsing (strings, numbers, booleans, objects, arrays, dates, etc.)\n * - Support for complex data structures including nested objects and arrays\n * - Reactive props that automatically update when parent data changes\n * - Comprehensive error handling with custom error callbacks\n * - Simple configuration with minimal setup required\n *\n * @example\n * // Install the plugin\n * const app = new Eleva(\"myApp\");\n * app.use(PropsPlugin, {\n * enableAutoParsing: true,\n * enableReactivity: true,\n * onError: (error, value) => {\n * console.error('Props parsing error:', error, value);\n * }\n * });\n *\n * // Use complex props in components\n * app.component(\"UserCard\", {\n * template: (ctx) => `\n * <div class=\"user-info-container\"\n * :user='${JSON.stringify(ctx.user.value)}'\n * :permissions='${JSON.stringify(ctx.permissions.value)}'\n * :settings='${JSON.stringify(ctx.settings.value)}'>\n * </div>\n * `,\n * children: {\n * '.user-info-container': 'UserInfo'\n * }\n * });\n *\n * app.component(\"UserInfo\", {\n * setup({ props }) {\n * return {\n * user: props.user, // Automatically parsed object\n * permissions: props.permissions, // Automatically parsed array\n * settings: props.settings // Automatically parsed object\n * };\n * }\n * });\n */\nexport const PropsPlugin = {\n /**\n * Unique identifier for the plugin\n * @type {string}\n */\n name: \"props\",\n\n /**\n * Plugin version\n * @type {string}\n */\n version: \"1.0.0-rc.1\",\n\n /**\n * Plugin description\n * @type {string}\n */\n description:\n \"Advanced props data handling for complex data structures with automatic type detection and reactivity\",\n\n /**\n * Installs the plugin into the Eleva instance\n *\n * @param {Object} eleva - The Eleva instance\n * @param {Object} options - Plugin configuration options\n * @param {boolean} [options.enableAutoParsing=true] - Enable automatic type detection and parsing\n * @param {boolean} [options.enableReactivity=true] - Enable reactive prop updates using Eleva's signal system\n * @param {Function} [options.onError=null] - Error handler function called when parsing fails\n *\n * @example\n * // Basic installation\n * app.use(PropsPlugin);\n *\n * // Installation with custom options\n * app.use(PropsPlugin, {\n * enableAutoParsing: true,\n * enableReactivity: false,\n * onError: (error, value) => {\n * console.error('Props parsing error:', error, value);\n * }\n * });\n */\n install(eleva, options = {}) {\n const {\n enableAutoParsing = true,\n enableReactivity = true,\n onError = null,\n } = options;\n\n /**\n * Detects the type of a given value\n * @private\n * @param {any} value - The value to detect type for\n * @returns {string} The detected type ('string', 'number', 'boolean', 'object', 'array', 'date', 'map', 'set', 'function', 'null', 'undefined', 'unknown')\n *\n * @example\n * detectType(\"hello\") // → \"string\"\n * detectType(42) // → \"number\"\n * detectType(true) // → \"boolean\"\n * detectType([1, 2, 3]) // → \"array\"\n * detectType({}) // → \"object\"\n * detectType(new Date()) // → \"date\"\n * detectType(null) // → \"null\"\n */\n const detectType = (value) => {\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (typeof value === \"boolean\") return \"boolean\";\n if (typeof value === \"number\") return \"number\";\n if (typeof value === \"string\") return \"string\";\n if (typeof value === \"function\") return \"function\";\n if (value instanceof Date) return \"date\";\n if (value instanceof Map) return \"map\";\n if (value instanceof Set) return \"set\";\n if (Array.isArray(value)) return \"array\";\n if (typeof value === \"object\") return \"object\";\n return \"unknown\";\n };\n\n /**\n * Parses a prop value with automatic type detection\n * @private\n * @param {any} value - The value to parse\n * @returns {any} The parsed value with appropriate type\n *\n * @description\n * This function automatically detects and parses different data types from string values:\n * - Special strings: \"true\" → true, \"false\" → false, \"null\" → null, \"undefined\" → undefined\n * - JSON objects/arrays: '{\"key\": \"value\"}' → {key: \"value\"}, '[1, 2, 3]' → [1, 2, 3]\n * - Boolean-like strings: \"1\" → true, \"0\" → false, \"\" → true\n * - Numeric strings: \"42\" → 42, \"3.14\" → 3.14\n * - Date strings: \"2023-01-01T00:00:00.000Z\" → Date object\n * - Other strings: returned as-is\n *\n * @example\n * parsePropValue(\"true\") // → true\n * parsePropValue(\"42\") // → 42\n * parsePropValue('{\"key\": \"val\"}') // → {key: \"val\"}\n * parsePropValue('[1, 2, 3]') // → [1, 2, 3]\n * parsePropValue(\"hello\") // → \"hello\"\n */\n const parsePropValue = (value) => {\n try {\n // Handle non-string values - return as-is\n if (typeof value !== \"string\") {\n return value;\n }\n\n // Handle special string patterns first\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n if (value === \"null\") return null;\n if (value === \"undefined\") return undefined;\n\n // Try to parse as JSON (for objects and arrays)\n // This handles complex data structures like objects and arrays\n if (value.startsWith(\"{\") || value.startsWith(\"[\")) {\n try {\n return JSON.parse(value);\n } catch (e) {\n // Not valid JSON, throw error to trigger error handler\n throw new Error(`Invalid JSON: ${value}`);\n }\n }\n\n // Handle boolean-like strings (including \"1\" and \"0\")\n // These are common in HTML attributes and should be treated as booleans\n if (value === \"1\") return true;\n if (value === \"0\") return false;\n if (value === \"\") return true; // Empty string is truthy in HTML attributes\n\n // Handle numeric strings (after boolean check to avoid conflicts)\n // This ensures \"0\" is treated as boolean false, not number 0\n if (!isNaN(value) && value !== \"\" && !isNaN(parseFloat(value))) {\n return Number(value);\n }\n\n // Handle date strings (ISO format)\n // Recognizes standard ISO date format and converts to Date object\n if (value.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/)) {\n const date = new Date(value);\n if (!isNaN(date.getTime())) {\n return date;\n }\n }\n\n // Return as string if no other parsing applies\n // This is the fallback for regular text strings\n return value;\n } catch (error) {\n // Call error handler if provided\n if (onError) {\n onError(error, value);\n }\n // Fallback to original value to prevent breaking the application\n return value;\n }\n };\n\n /**\n * Enhanced props extraction with automatic type detection\n * @private\n * @param {HTMLElement} element - The DOM element to extract props from\n * @returns {Object} Object containing parsed props with appropriate types\n *\n * @description\n * Extracts props from DOM element attributes that start with \":\" and automatically\n * parses them to their appropriate types. Removes the attributes from the element\n * after extraction.\n *\n * @example\n * // HTML: <div :name=\"John\" :age=\"30\" :active=\"true\" :data='{\"key\": \"value\"}'></div>\n * const props = extractProps(element);\n * // Result: { name: \"John\", age: 30, active: true, data: {key: \"value\"} }\n */\n const extractProps = (element) => {\n const props = {};\n const attrs = element.attributes;\n\n // Iterate through attributes in reverse order to handle removal correctly\n for (let i = attrs.length - 1; i >= 0; i--) {\n const attr = attrs[i];\n // Only process attributes that start with \":\" (prop attributes)\n if (attr.name.startsWith(\":\")) {\n const propName = attr.name.slice(1); // Remove the \":\" prefix\n // Parse the value if auto-parsing is enabled, otherwise use as-is\n const parsedValue = enableAutoParsing\n ? parsePropValue(attr.value)\n : attr.value;\n props[propName] = parsedValue;\n // Remove the attribute from the DOM element after extraction\n element.removeAttribute(attr.name);\n }\n }\n\n return props;\n };\n\n /**\n * Creates reactive props using Eleva's signal system\n * @private\n * @param {Object} props - The props object to make reactive\n * @returns {Object} Object containing reactive props (Eleva signals)\n *\n * @description\n * Converts regular prop values into Eleva signals for reactive updates.\n * If a value is already a signal, it's passed through unchanged.\n *\n * @example\n * const props = { name: \"John\", age: 30, active: true };\n * const reactiveProps = createReactiveProps(props);\n * // Result: {\n * // name: Signal(\"John\"),\n * // age: Signal(30),\n * // active: Signal(true)\n * // }\n */\n const createReactiveProps = (props) => {\n const reactiveProps = {};\n\n // Convert each prop value to a reactive signal\n Object.entries(props).forEach(([key, value]) => {\n // Check if value is already a signal (has 'value' and 'watch' properties)\n if (\n value &&\n typeof value === \"object\" &&\n \"value\" in value &&\n \"watch\" in value\n ) {\n // Value is already a signal, use it as-is\n reactiveProps[key] = value;\n } else {\n // Create new signal for the prop value to make it reactive\n reactiveProps[key] = new eleva.signal(value);\n }\n });\n\n return reactiveProps;\n };\n\n // Override Eleva's internal _extractProps method with our enhanced version\n eleva._extractProps = extractProps;\n\n // Override Eleva's mount method to apply enhanced prop handling\n const originalMount = eleva.mount;\n eleva.mount = async (container, compName, props = {}) => {\n // Create reactive props if reactivity is enabled\n const enhancedProps = enableReactivity\n ? createReactiveProps(props)\n : props;\n\n // Call the original mount method with enhanced props\n return await originalMount.call(\n eleva,\n container,\n compName,\n enhancedProps\n );\n };\n\n /**\n * Expose utility methods on the Eleva instance\n * @namespace eleva.props\n */\n eleva.props = {\n /**\n * Parse a single value with automatic type detection\n * @param {any} value - The value to parse\n * @returns {any} The parsed value with appropriate type\n *\n * @example\n * app.props.parse(\"42\") // → 42\n * app.props.parse(\"true\") // → true\n * app.props.parse('{\"key\": \"val\"}') // → {key: \"val\"}\n */\n parse: (value) => {\n // Return value as-is if auto parsing is disabled\n if (!enableAutoParsing) {\n return value;\n }\n // Use our enhanced parsing function\n return parsePropValue(value);\n },\n\n /**\n * Detect the type of a value\n * @param {any} value - The value to detect type for\n * @returns {string} The detected type\n *\n * @example\n * app.props.detectType(\"hello\") // → \"string\"\n * app.props.detectType(42) // → \"number\"\n * app.props.detectType([1, 2, 3]) // → \"array\"\n */\n detectType,\n };\n\n // Store original methods for uninstall\n eleva._originalExtractProps = eleva._extractProps;\n eleva._originalMount = originalMount;\n },\n\n /**\n * Uninstalls the plugin from the Eleva instance\n *\n * @param {Object} eleva - The Eleva instance\n *\n * @description\n * Restores the original Eleva methods and removes all plugin-specific\n * functionality. This method should be called when the plugin is no\n * longer needed.\n *\n * @example\n * // Uninstall the plugin\n * PropsPlugin.uninstall(app);\n */\n uninstall(eleva) {\n // Restore original _extractProps method\n if (eleva._originalExtractProps) {\n eleva._extractProps = eleva._originalExtractProps;\n delete eleva._originalExtractProps;\n }\n\n // Restore original mount method\n if (eleva._originalMount) {\n eleva.mount = eleva._originalMount;\n delete eleva._originalMount;\n }\n\n // Remove plugin utility methods\n if (eleva.props) {\n delete eleva.props;\n }\n },\n};\n"],"names":["name","version","description","install","eleva","options","enableAutoParsing","enableReactivity","onError","parsePropValue","value","startsWith","JSON","parse","e","Error","isNaN","parseFloat","Number","match","date","Date","getTime","error","_extractProps","element","props","attrs","attributes","i","length","attr","propName","slice","parsedValue","removeAttribute","originalMount","mount","async","container","compName","enhancedProps","reactiveProps","Object","entries","forEach","key","signal","createReactiveProps","call","detectType","undefined","Map","Set","Array","isArray","_originalExtractProps","_originalMount","uninstall"],"mappings":";wDAkD2B,CAKzBA,KAAM,QAMNC,QAAS,aAMTC,YACE,wGAwBFC,OAAAA,CAAQC,EAAOC,EAAU,IACvB,MAAMC,kBACJA,GAAoB,EAAIC,iBACxBA,GAAmB,EAAIC,QACvBA,EAAU,MACRH,EAsDEI,EAAkBC,IACtB,IAEE,GAAqB,iBAAVA,EACT,OAAOA,EAIT,GAAc,SAAVA,EAAkB,OAAO,EAC7B,GAAc,UAAVA,EAAmB,OAAO,EAC9B,GAAc,SAAVA,EAAkB,OAAO,KAC7B,GAAc,cAAVA,EAAuB,OAI3B,GAAIA,EAAMC,WAAW,MAAQD,EAAMC,WAAW,KAC5C,IACE,OAAOC,KAAKC,MAAMH,EACpB,CAAE,MAAOI,GAEP,MAAM,IAAIC,MAAM,iBAAiBL,IACnC,CAKF,GAAc,MAAVA,EAAe,OAAO,EAC1B,GAAc,MAAVA,EAAe,OAAO,EAC1B,GAAc,KAAVA,EAAc,OAAO,EAIzB,IAAKM,MAAMN,IAAoB,KAAVA,IAAiBM,MAAMC,WAAWP,IACrD,OAAOQ,OAAOR,GAKhB,GAAIA,EAAMS,MAAM,wCAAyC,CACvD,MAAMC,EAAO,IAAIC,KAAKX,GACtB,IAAKM,MAAMI,EAAKE,WACd,OAAOF,CAEX,CAIA,OAAOV,CACT,CAAE,MAAOa,GAMP,OAJIf,GACFA,EAAQe,EAAOb,GAGVA,CACT,GAqFFN,EAAMoB,cAlEgBC,IACpB,MAAMC,EAAQ,CAAA,EACRC,EAAQF,EAAQG,WAGtB,IAAK,IAAIC,EAAIF,EAAMG,OAAS,EAAGD,GAAK,EAAGA,IAAK,CAC1C,MAAME,EAAOJ,EAAME,GAEnB,GAAIE,EAAK/B,KAAKW,WAAW,KAAM,CAC7B,MAAMqB,EAAWD,EAAK/B,KAAKiC,MAAM,GAE3BC,EAAc5B,EAChBG,EAAesB,EAAKrB,OACpBqB,EAAKrB,MACTgB,EAAMM,GAAYE,EAElBT,EAAQU,gBAAgBJ,EAAK/B,KAC/B,CACF,CAEA,OAAO0B,GAiDT,MAAMU,EAAgBhC,EAAMiC,MAC5BjC,EAAMiC,MAAQC,MAAOC,EAAWC,EAAUd,EAAQ,CAAA,KAEhD,MAAMe,EAAgBlC,EA9BKmB,KAC3B,MAAMgB,EAAgB,CAAA,EAmBtB,OAhBAC,OAAOC,QAAQlB,GAAOmB,QAAQ,EAAEC,EAAKpC,MASjCgC,EAAcI,GANdpC,GACiB,iBAAVA,GACP,UAAWA,GACX,UAAWA,EAGUA,EAGA,IAAIN,EAAM2C,OAAOrC,KAInCgC,GAWHM,CAAoBtB,GACpBA,EAGJ,aAAaU,EAAca,KACzB7C,EACAmC,EACAC,EACAC,IAQJrC,EAAMsB,MAAQ,CAWZb,MAAQH,GAEDJ,EAIEG,EAAeC,GAHbA,EAgBXwC,WAtOkBxC,GACJ,OAAVA,EAAuB,YACbyC,IAAVzC,EAA4B,YACX,kBAAVA,EAA4B,UAClB,iBAAVA,EAA2B,SACjB,iBAAVA,EAA2B,SACjB,mBAAVA,EAA6B,WACpCA,aAAiBW,KAAa,OAC9BX,aAAiB0C,IAAY,MAC7B1C,aAAiB2C,IAAY,MAC7BC,MAAMC,QAAQ7C,GAAe,QACZ,iBAAVA,EAA2B,SAC/B,WA8NTN,EAAMoD,sBAAwBpD,EAAMoB,cACpCpB,EAAMqD,eAAiBrB,CACzB,EAgBAsB,SAAAA,CAAUtD,GAEJA,EAAMoD,wBACRpD,EAAMoB,cAAgBpB,EAAMoD,6BACrBpD,EAAMoD,uBAIXpD,EAAMqD,iBACRrD,EAAMiC,MAAQjC,EAAMqD,sBACbrD,EAAMqD,gBAIXrD,EAAMsB,cACDtB,EAAMsB,KAEjB"}
1
+ {"version":3,"file":"props.umd.min.js","sources":["../../src/modules/TemplateEngine.js","../../src/plugins/Props.js"],"sourcesContent":["\"use strict\";\n\n/**\n * @class 🔒 TemplateEngine\n * @classdesc A secure template engine that handles interpolation and dynamic attribute parsing.\n * Provides a safe way to evaluate expressions in templates while preventing XSS attacks.\n * All methods are static and can be called directly on the class.\n *\n * @example\n * const template = \"Hello, {{name}}!\";\n * const data = { name: \"World\" };\n * const result = TemplateEngine.parse(template, data); // Returns: \"Hello, World!\"\n */\nexport class TemplateEngine {\n /**\n * @private {RegExp} Regular expression for matching template expressions in the format {{ expression }}\n * @type {RegExp}\n */\n static expressionPattern = /\\{\\{\\s*(.*?)\\s*\\}\\}/g;\n\n /**\n * Parses a template string, replacing expressions with their evaluated values.\n * Expressions are evaluated in the provided data context.\n *\n * @public\n * @static\n * @param {string} template - The template string to parse.\n * @param {Record<string, unknown>} data - The data context for evaluating expressions.\n * @returns {string} The parsed template with expressions replaced by their values.\n * @example\n * const result = TemplateEngine.parse(\"{{user.name}} is {{user.age}} years old\", {\n * user: { name: \"John\", age: 30 }\n * }); // Returns: \"John is 30 years old\"\n */\n static parse(template, data) {\n if (typeof template !== \"string\") return template;\n return template.replace(this.expressionPattern, (_, expression) =>\n this.evaluate(expression, data)\n );\n }\n\n /**\n * Evaluates an expression in the context of the provided data object.\n * Note: This does not provide a true sandbox and evaluated expressions may access global scope.\n * The use of the `with` statement is necessary for expression evaluation but has security implications.\n * Expressions should be carefully validated before evaluation.\n *\n * @public\n * @static\n * @param {string} expression - The expression to evaluate.\n * @param {Record<string, unknown>} data - The data context for evaluation.\n * @returns {unknown} The result of the evaluation, or an empty string if evaluation fails.\n * @example\n * const result = TemplateEngine.evaluate(\"user.name\", { user: { name: \"John\" } }); // Returns: \"John\"\n * const age = TemplateEngine.evaluate(\"user.age\", { user: { age: 30 } }); // Returns: 30\n */\n static evaluate(expression, data) {\n if (typeof expression !== \"string\") return expression;\n try {\n return new Function(\"data\", `with(data) { return ${expression}; }`)(data);\n } catch {\n return \"\";\n }\n }\n}\n","\"use strict\";\n\nimport { TemplateEngine } from \"../modules/TemplateEngine.js\";\n\n/**\n * @class 🎯 PropsPlugin\n * @classdesc A plugin that extends Eleva's props data handling to support any type of data structure\n * with automatic type detection, parsing, and reactive prop updates. This plugin enables seamless\n * passing of complex data types from parent to child components without manual parsing.\n *\n * Core Features:\n * - Automatic type detection and parsing (strings, numbers, booleans, objects, arrays, dates, etc.)\n * - Support for complex data structures including nested objects and arrays\n * - Reactive props that automatically update when parent data changes\n * - Comprehensive error handling with custom error callbacks\n * - Simple configuration with minimal setup required\n *\n * @example\n * // Install the plugin\n * const app = new Eleva(\"myApp\");\n * app.use(PropsPlugin, {\n * enableAutoParsing: true,\n * enableReactivity: true,\n * onError: (error, value) => {\n * console.error('Props parsing error:', error, value);\n * }\n * });\n *\n * // Use complex props in components\n * app.component(\"UserCard\", {\n * template: (ctx) => `\n * <div class=\"user-info-container\"\n * :user='${JSON.stringify(ctx.user.value)}'\n * :permissions='${JSON.stringify(ctx.permissions.value)}'\n * :settings='${JSON.stringify(ctx.settings.value)}'>\n * </div>\n * `,\n * children: {\n * '.user-info-container': 'UserInfo'\n * }\n * });\n *\n * app.component(\"UserInfo\", {\n * setup({ props }) {\n * return {\n * user: props.user, // Automatically parsed object\n * permissions: props.permissions, // Automatically parsed array\n * settings: props.settings // Automatically parsed object\n * };\n * }\n * });\n */\nexport const PropsPlugin = {\n /**\n * Unique identifier for the plugin\n * @type {string}\n */\n name: \"props\",\n\n /**\n * Plugin version\n * @type {string}\n */\n version: \"1.0.0-rc.2\",\n\n /**\n * Plugin description\n * @type {string}\n */\n description:\n \"Advanced props data handling for complex data structures with automatic type detection and reactivity\",\n\n /**\n * Installs the plugin into the Eleva instance\n *\n * @param {Object} eleva - The Eleva instance\n * @param {Object} options - Plugin configuration options\n * @param {boolean} [options.enableAutoParsing=true] - Enable automatic type detection and parsing\n * @param {boolean} [options.enableReactivity=true] - Enable reactive prop updates using Eleva's signal system\n * @param {Function} [options.onError=null] - Error handler function called when parsing fails\n *\n * @example\n * // Basic installation\n * app.use(PropsPlugin);\n *\n * // Installation with custom options\n * app.use(PropsPlugin, {\n * enableAutoParsing: true,\n * enableReactivity: false,\n * onError: (error, value) => {\n * console.error('Props parsing error:', error, value);\n * }\n * });\n */\n install(eleva, options = {}) {\n const {\n enableAutoParsing = true,\n enableReactivity = true,\n onError = null,\n } = options;\n\n /**\n * Detects the type of a given value\n * @private\n * @param {any} value - The value to detect type for\n * @returns {string} The detected type ('string', 'number', 'boolean', 'object', 'array', 'date', 'map', 'set', 'function', 'null', 'undefined', 'unknown')\n *\n * @example\n * detectType(\"hello\") // → \"string\"\n * detectType(42) // → \"number\"\n * detectType(true) // → \"boolean\"\n * detectType([1, 2, 3]) // → \"array\"\n * detectType({}) // → \"object\"\n * detectType(new Date()) // → \"date\"\n * detectType(null) // → \"null\"\n */\n const detectType = (value) => {\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (typeof value === \"boolean\") return \"boolean\";\n if (typeof value === \"number\") return \"number\";\n if (typeof value === \"string\") return \"string\";\n if (typeof value === \"function\") return \"function\";\n if (value instanceof Date) return \"date\";\n if (value instanceof Map) return \"map\";\n if (value instanceof Set) return \"set\";\n if (Array.isArray(value)) return \"array\";\n if (typeof value === \"object\") return \"object\";\n return \"unknown\";\n };\n\n /**\n * Parses a prop value with automatic type detection\n * @private\n * @param {any} value - The value to parse\n * @returns {any} The parsed value with appropriate type\n *\n * @description\n * This function automatically detects and parses different data types from string values:\n * - Special strings: \"true\" → true, \"false\" → false, \"null\" → null, \"undefined\" → undefined\n * - JSON objects/arrays: '{\"key\": \"value\"}' → {key: \"value\"}, '[1, 2, 3]' → [1, 2, 3]\n * - Boolean-like strings: \"1\" → true, \"0\" → false, \"\" → true\n * - Numeric strings: \"42\" → 42, \"3.14\" → 3.14\n * - Date strings: \"2023-01-01T00:00:00.000Z\" → Date object\n * - Other strings: returned as-is\n *\n * @example\n * parsePropValue(\"true\") // → true\n * parsePropValue(\"42\") // → 42\n * parsePropValue('{\"key\": \"val\"}') // → {key: \"val\"}\n * parsePropValue('[1, 2, 3]') // → [1, 2, 3]\n * parsePropValue(\"hello\") // → \"hello\"\n */\n const parsePropValue = (value) => {\n try {\n // Handle non-string values - return as-is\n if (typeof value !== \"string\") {\n return value;\n }\n\n // Handle special string patterns first\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n if (value === \"null\") return null;\n if (value === \"undefined\") return undefined;\n\n // Try to parse as JSON (for objects and arrays)\n // This handles complex data structures like objects and arrays\n if (value.startsWith(\"{\") || value.startsWith(\"[\")) {\n try {\n return JSON.parse(value);\n } catch (e) {\n // Not valid JSON, throw error to trigger error handler\n throw new Error(`Invalid JSON: ${value}`);\n }\n }\n\n // Handle boolean-like strings (including \"1\" and \"0\")\n // These are common in HTML attributes and should be treated as booleans\n if (value === \"1\") return true;\n if (value === \"0\") return false;\n if (value === \"\") return true; // Empty string is truthy in HTML attributes\n\n // Handle numeric strings (after boolean check to avoid conflicts)\n // This ensures \"0\" is treated as boolean false, not number 0\n if (!isNaN(value) && value !== \"\" && !isNaN(parseFloat(value))) {\n return Number(value);\n }\n\n // Handle date strings (ISO format)\n // Recognizes standard ISO date format and converts to Date object\n if (value.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/)) {\n const date = new Date(value);\n if (!isNaN(date.getTime())) {\n return date;\n }\n }\n\n // Return as string if no other parsing applies\n // This is the fallback for regular text strings\n return value;\n } catch (error) {\n // Call error handler if provided\n if (onError) {\n onError(error, value);\n }\n // Fallback to original value to prevent breaking the application\n return value;\n }\n };\n\n /**\n * Enhanced props extraction with automatic type detection\n * @private\n * @param {HTMLElement} element - The DOM element to extract props from\n * @returns {Object} Object containing parsed props with appropriate types\n *\n * @description\n * Extracts props from DOM element attributes that start with \":\" and automatically\n * parses them to their appropriate types. Removes the attributes from the element\n * after extraction.\n *\n * @example\n * // HTML: <div :name=\"John\" :age=\"30\" :active=\"true\" :data='{\"key\": \"value\"}'></div>\n * const props = extractProps(element);\n * // Result: { name: \"John\", age: 30, active: true, data: {key: \"value\"} }\n */\n const extractProps = (element) => {\n const props = {};\n const attrs = element.attributes;\n\n // Iterate through attributes in reverse order to handle removal correctly\n for (let i = attrs.length - 1; i >= 0; i--) {\n const attr = attrs[i];\n // Only process attributes that start with \":\" (prop attributes)\n if (attr.name.startsWith(\":\")) {\n const propName = attr.name.slice(1); // Remove the \":\" prefix\n // Parse the value if auto-parsing is enabled, otherwise use as-is\n const parsedValue = enableAutoParsing\n ? parsePropValue(attr.value)\n : attr.value;\n props[propName] = parsedValue;\n // Remove the attribute from the DOM element after extraction\n element.removeAttribute(attr.name);\n }\n }\n\n return props;\n };\n\n /**\n * Creates reactive props using Eleva's signal system\n * @private\n * @param {Object} props - The props object to make reactive\n * @returns {Object} Object containing reactive props (Eleva signals)\n *\n * @description\n * Converts regular prop values into Eleva signals for reactive updates.\n * If a value is already a signal, it's passed through unchanged.\n *\n * @example\n * const props = { name: \"John\", age: 30, active: true };\n * const reactiveProps = createReactiveProps(props);\n * // Result: {\n * // name: Signal(\"John\"),\n * // age: Signal(30),\n * // active: Signal(true)\n * // }\n */\n const createReactiveProps = (props) => {\n const reactiveProps = {};\n\n // Convert each prop value to a reactive signal\n Object.entries(props).forEach(([key, value]) => {\n // Check if value is already a signal (has 'value' and 'watch' properties)\n if (\n value &&\n typeof value === \"object\" &&\n \"value\" in value &&\n \"watch\" in value\n ) {\n // Value is already a signal, use it as-is\n reactiveProps[key] = value;\n } else {\n // Create new signal for the prop value to make it reactive\n reactiveProps[key] = new eleva.signal(value);\n }\n });\n\n return reactiveProps;\n };\n\n // Override Eleva's internal _extractProps method with our enhanced version\n eleva._extractProps = extractProps;\n\n // Override Eleva's mount method to apply enhanced prop handling\n const originalMount = eleva.mount;\n eleva.mount = async (container, compName, props = {}) => {\n // Create reactive props if reactivity is enabled\n const enhancedProps = enableReactivity\n ? createReactiveProps(props)\n : props;\n\n // Call the original mount method with enhanced props\n return await originalMount.call(\n eleva,\n container,\n compName,\n enhancedProps\n );\n };\n\n // Override Eleva's _mountComponents method to enable signal reference passing\n const originalMountComponents = eleva._mountComponents;\n\n // Cache to store parent contexts by container element\n const parentContextCache = new WeakMap();\n // Store child instances that need signal linking\n const pendingSignalLinks = new Set();\n\n eleva._mountComponents = async (container, children, childInstances) => {\n for (const [selector, component] of Object.entries(children)) {\n if (!selector) continue;\n for (const el of container.querySelectorAll(selector)) {\n if (!(el instanceof HTMLElement)) continue;\n\n // Extract props from DOM attributes\n const extractedProps = eleva._extractProps(el);\n\n // Get parent context to check for signal references\n let enhancedProps = extractedProps;\n\n // Try to find parent context by looking up the DOM tree\n let parentContext = parentContextCache.get(container);\n if (!parentContext) {\n let currentElement = container;\n while (currentElement && !parentContext) {\n if (\n currentElement._eleva_instance &&\n currentElement._eleva_instance.data\n ) {\n parentContext = currentElement._eleva_instance.data;\n // Cache the parent context for future use\n parentContextCache.set(container, parentContext);\n break;\n }\n currentElement = currentElement.parentElement;\n }\n }\n\n if (enableReactivity && parentContext) {\n const signalProps = {};\n\n // Check each extracted prop to see if there's a matching signal in parent context\n Object.keys(extractedProps).forEach((propName) => {\n if (\n parentContext[propName] &&\n parentContext[propName] instanceof eleva.signal\n ) {\n // Found a signal in parent context with the same name as the prop\n // Pass the signal reference instead of creating a new one\n signalProps[propName] = parentContext[propName];\n }\n });\n\n // Merge signal props with regular props (signal props take precedence)\n enhancedProps = {\n ...extractedProps,\n ...signalProps,\n };\n }\n\n // Create reactive props for non-signal props only\n let finalProps = enhancedProps;\n if (enableReactivity) {\n // Only create reactive props for values that aren't already signals\n const nonSignalProps = {};\n Object.entries(enhancedProps).forEach(([key, value]) => {\n if (\n !(\n value &&\n typeof value === \"object\" &&\n \"value\" in value &&\n \"watch\" in value\n )\n ) {\n // This is not a signal, create a reactive prop for it\n nonSignalProps[key] = value;\n }\n });\n\n // Create reactive props only for non-signal values\n const reactiveNonSignalProps = createReactiveProps(nonSignalProps);\n\n // Merge signal props with reactive non-signal props\n finalProps = {\n ...reactiveNonSignalProps,\n ...enhancedProps, // Signal props take precedence\n };\n }\n\n /** @type {MountResult} */\n const instance = await eleva.mount(el, component, finalProps);\n if (instance && !childInstances.includes(instance)) {\n childInstances.push(instance);\n\n // If we have extracted props but no parent context yet, mark for later signal linking\n if (\n enableReactivity &&\n Object.keys(extractedProps).length > 0 &&\n !parentContext\n ) {\n pendingSignalLinks.add({\n instance,\n extractedProps,\n container,\n component,\n });\n }\n }\n }\n }\n\n // After mounting all children, try to link signals for pending instances\n if (enableReactivity && pendingSignalLinks.size > 0) {\n for (const pending of pendingSignalLinks) {\n const { instance, extractedProps, container, component } = pending;\n\n // Try to find parent context again\n let parentContext = parentContextCache.get(container);\n if (!parentContext) {\n let currentElement = container;\n while (currentElement && !parentContext) {\n if (\n currentElement._eleva_instance &&\n currentElement._eleva_instance.data\n ) {\n parentContext = currentElement._eleva_instance.data;\n parentContextCache.set(container, parentContext);\n break;\n }\n currentElement = currentElement.parentElement;\n }\n }\n\n if (parentContext) {\n const signalProps = {};\n\n // Check each extracted prop to see if there's a matching signal in parent context\n Object.keys(extractedProps).forEach((propName) => {\n if (\n parentContext[propName] &&\n parentContext[propName] instanceof eleva.signal\n ) {\n signalProps[propName] = parentContext[propName];\n }\n });\n\n // Update the child instance's data with signal references\n if (Object.keys(signalProps).length > 0) {\n Object.assign(instance.data, signalProps);\n\n // Set up signal watchers for the newly linked signals\n Object.keys(signalProps).forEach((propName) => {\n const signal = signalProps[propName];\n if (signal && typeof signal.watch === \"function\") {\n signal.watch((newValue) => {\n // Trigger a re-render of the child component when the signal changes\n const childComponent =\n eleva._components.get(component) || component;\n if (childComponent && childComponent.template) {\n const templateResult =\n typeof childComponent.template === \"function\"\n ? childComponent.template(instance.data)\n : childComponent.template;\n const newHtml = TemplateEngine.parse(\n templateResult,\n instance.data\n );\n eleva.renderer.patchDOM(instance.container, newHtml);\n }\n });\n }\n });\n\n // Initial re-render to show the correct signal values\n const childComponent =\n eleva._components.get(component) || component;\n if (childComponent && childComponent.template) {\n const templateResult =\n typeof childComponent.template === \"function\"\n ? childComponent.template(instance.data)\n : childComponent.template;\n const newHtml = TemplateEngine.parse(\n templateResult,\n instance.data\n );\n eleva.renderer.patchDOM(instance.container, newHtml);\n }\n }\n\n // Remove from pending list\n pendingSignalLinks.delete(pending);\n }\n }\n }\n };\n\n /**\n * Expose utility methods on the Eleva instance\n * @namespace eleva.props\n */\n eleva.props = {\n /**\n * Parse a single value with automatic type detection\n * @param {any} value - The value to parse\n * @returns {any} The parsed value with appropriate type\n *\n * @example\n * app.props.parse(\"42\") // → 42\n * app.props.parse(\"true\") // → true\n * app.props.parse('{\"key\": \"val\"}') // → {key: \"val\"}\n */\n parse: (value) => {\n // Return value as-is if auto parsing is disabled\n if (!enableAutoParsing) {\n return value;\n }\n // Use our enhanced parsing function\n return parsePropValue(value);\n },\n\n /**\n * Detect the type of a value\n * @param {any} value - The value to detect type for\n * @returns {string} The detected type\n *\n * @example\n * app.props.detectType(\"hello\") // → \"string\"\n * app.props.detectType(42) // → \"number\"\n * app.props.detectType([1, 2, 3]) // → \"array\"\n */\n detectType,\n };\n\n // Store original methods for uninstall\n eleva._originalExtractProps = eleva._extractProps;\n eleva._originalMount = originalMount;\n eleva._originalMountComponents = originalMountComponents;\n },\n\n /**\n * Uninstalls the plugin from the Eleva instance\n *\n * @param {Object} eleva - The Eleva instance\n *\n * @description\n * Restores the original Eleva methods and removes all plugin-specific\n * functionality. This method should be called when the plugin is no\n * longer needed.\n *\n * @example\n * // Uninstall the plugin\n * PropsPlugin.uninstall(app);\n */\n uninstall(eleva) {\n // Restore original _extractProps method\n if (eleva._originalExtractProps) {\n eleva._extractProps = eleva._originalExtractProps;\n delete eleva._originalExtractProps;\n }\n\n // Restore original mount method\n if (eleva._originalMount) {\n eleva.mount = eleva._originalMount;\n delete eleva._originalMount;\n }\n\n // Restore original _mountComponents method\n if (eleva._originalMountComponents) {\n eleva._mountComponents = eleva._originalMountComponents;\n delete eleva._originalMountComponents;\n }\n\n // Remove plugin utility methods\n if (eleva.props) {\n delete eleva.props;\n }\n },\n};\n"],"names":["TemplateEngine","static","parse","template","data","replace","this","expressionPattern","_","expression","evaluate","Function","name","version","description","install","eleva","options","enableAutoParsing","enableReactivity","onError","parsePropValue","value","startsWith","JSON","e","Error","isNaN","parseFloat","Number","match","date","Date","getTime","error","createReactiveProps","props","reactiveProps","Object","entries","forEach","key","signal","_extractProps","element","attrs","attributes","i","length","attr","propName","slice","parsedValue","removeAttribute","originalMount","mount","async","container","compName","enhancedProps","call","originalMountComponents","_mountComponents","parentContextCache","WeakMap","pendingSignalLinks","Set","children","childInstances","selector","component","el","querySelectorAll","HTMLElement","extractedProps","parentContext","get","currentElement","_eleva_instance","set","parentElement","signalProps","keys","finalProps","nonSignalProps","instance","includes","push","add","size","pending","assign","watch","newValue","childComponent","_components","templateResult","newHtml","renderer","patchDOM","delete","detectType","undefined","Map","Array","isArray","_originalExtractProps","_originalMount","_originalMountComponents","uninstall"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eleva",
3
- "version": "1.0.0-rc.5",
3
+ "version": "1.0.0-rc.6",
4
4
  "description": "A minimalist and lightweight, pure vanilla JavaScript frontend runtime framework.",
5
5
  "type": "module",
6
6
  "private": false,