@elenajs/core 1.0.0-rc.7 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,13 +1,14 @@
1
+ <br/>
1
2
  <div align="center">
2
3
  <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="https://elenajs.com/img/elena-dark.png" alt="Elena" width="558" height="220">
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://elenajs.com/elena-v2-dark.png" alt="Elena" width="127" height="156">
4
5
  </source>
5
- <source media="(prefers-color-scheme: light)" srcset="https://elenajs.com/img/elena-light.png" alt="Elena" width="558" height="220">
6
+ <source media="(prefers-color-scheme: light)" srcset="https://elenajs.com/elena-v3.png" alt="Elena" width="127" height="156">
6
7
  </source>
7
- <img src="https://elenajs.com/img/elena-light.png" alt="Elena" width="558" height="220">
8
+ <img src="https://elenajs.com/elena-v2.png" alt="Elena" width="127" height="156">
8
9
  </picture>
9
10
 
10
- ### Simple, tiny library for building Progressive Web Components.
11
+ ### Simple, tiny library for building Progressive Web Components
11
12
 
12
13
  <br/>
13
14
 
@@ -22,44 +23,80 @@
22
23
 
23
24
  <br/>
24
25
 
25
- <p align="center">Elena is a simple, tiny library (2.6kB) for building <a href="https://elenajs.com/">Progressive Web Components</a>. Unlike most web component libraries, Elena doesn’t force JavaScript for everything. You can load HTML and CSS first, then use JavaScript to progressively add interactivity.</p>
26
+ <p align="center">Elena is a simple, tiny library for building <a href="https://elenajs.com/">Progressive Web Components</a>. Unlike most web component libraries, Elena doesn’t force JavaScript for everything. You can load HTML and CSS first, then use JavaScript to progressively add interactivity.</p>
27
+
28
+ ## Features
29
+
30
+ - 🔋 **Extremely lightweight:** 2.9kB minified & compressed, simple and tiny by design.
31
+ - 📈 **Progressively enhanced:** Renders HTML & CSS first, then hydrates with JavaScript.
32
+ - 🫶 **Accessible by default:** Semantic HTML foundation with no Shadow DOM barriers.
33
+ - 🌍 **Standards based:** Built entirely on native custom elements & web standards.
34
+ - ⚡ **Reactive updates:** Prop and state changes trigger efficient, batched re-renders.
35
+ - 🎨 **Scoped styles:** Simple & clean CSS encapsulation without complex workarounds.
36
+ - 🖥️ **SSR friendly:** Works out of the box, with optional server-side utilities if needed.
37
+ - 🧩 **Zero dependencies:** No runtime dependencies, runs entirely on the web platform.
38
+ - 🔓 **Zero lock-in:** Works with every major framework, or no framework at all.
26
39
 
27
- ## Documentation
40
+ ## Usage
28
41
 
29
- See the full documentation for Elena at [elenajs.com](https://elenajs.com).
42
+ To install Elena as a dependency, run:
30
43
 
31
44
  ```sh
32
45
  npm install @elenajs/core
33
46
  ```
34
47
 
35
- ## Packages
48
+ Then import Elena in a web component:
36
49
 
37
- Elena is a monorepo containing several packages published to npm under the `@elenajs` scope. These are the main packages intended for development:
50
+ ```js
51
+ import { Elena } from "@elenajs/core";
38
52
 
39
- | Package | Description | Version | Stability |
40
- | --- | --- | --- | --- |
41
- | [`@elenajs/core`](https://github.com/getelena/elena/tree/main/packages/core) | Elena core runtime library. | [![npm](https://img.shields.io/npm/v/@elenajs/core.svg)](https://www.npmjs.com/package/@elenajs/core) | ![stability-release-candidate](https://img.shields.io/badge/stability-pre--release-48c9b0.svg) |
42
- | [`@elenajs/components`](https://github.com/getelena/elena/tree/main/packages/components) | Elena demo web components. | [![npm](https://img.shields.io/npm/v/@elenajs/components.svg)](https://www.npmjs.com/package/@elenajs/components) | ![stability-release-candidate](https://img.shields.io/badge/stability-pre--release-48c9b0.svg) |
43
- | [`@elenajs/bundler`](https://github.com/getelena/elena/tree/main/packages/bundler) | Elena bundler for component libraries. | [![npm](https://img.shields.io/npm/v/@elenajs/bundler.svg)](https://www.npmjs.com/package/@elenajs/bundler) | ![stability-release-candidate](https://img.shields.io/badge/stability-pre--release-48c9b0.svg) |
44
- | [`@elenajs/cli`](https://github.com/getelena/elena/tree/main/packages/cli) | Elena CLI for scaffolding web components. | [![npm](https://img.shields.io/npm/v/@elenajs/cli.svg)](https://www.npmjs.com/package/@elenajs/cli) | ![stability-release-candidate](https://img.shields.io/badge/stability-pre--release-48c9b0.svg) |
45
- | [`@elenajs/plugin-cem-define`](https://github.com/getelena/elena/tree/main/packages/plugin-cem-define) | Elena CEM Define plugin. | [![npm](https://img.shields.io/npm/v/@elenajs/plugin-cem-define.svg)](https://www.npmjs.com/package/@elenajs/plugin-cem-define) | ![stability-release-candidate](https://img.shields.io/badge/stability-pre--release-48c9b0.svg) |
46
- | [`@elenajs/plugin-cem-prop`](https://github.com/getelena/elena/tree/main/packages/plugin-cem-prop) | Elena CEM Prop plugin. | [![npm](https://img.shields.io/npm/v/@elenajs/plugin-cem-prop.svg)](https://www.npmjs.com/package/@elenajs/plugin-cem-prop) | ![stability-release-candidate](https://img.shields.io/badge/stability-pre--release-48c9b0.svg) |
47
- | [`@elenajs/plugin-cem-tag`](https://github.com/getelena/elena/tree/main/packages/plugin-cem-tag) | Elena CEM Tag plugin. | [![npm](https://img.shields.io/npm/v/@elenajs/plugin-cem-tag.svg)](https://www.npmjs.com/package/@elenajs/plugin-cem-tag) | ![stability-release-candidate](https://img.shields.io/badge/stability-pre--release-48c9b0.svg) |
48
- | [`@elenajs/plugin-cem-typescript`](https://github.com/getelena/elena/tree/main/packages/plugin-cem-typescript) | Elena CEM TypeScript plugin. | [![npm](https://img.shields.io/npm/v/@elenajs/plugin-cem-typescript.svg)](https://www.npmjs.com/package/@elenajs/plugin-cem-typescript) | ![stability-release-candidate](https://img.shields.io/badge/stability-pre--release-48c9b0.svg) |
49
- | [`@elenajs/plugin-rollup-css`](https://github.com/getelena/elena/tree/main/packages/plugin-rollup-css) | Elena Rollup CSS plugin. | [![npm](https://img.shields.io/npm/v/@elenajs/plugin-rollup-css.svg)](https://www.npmjs.com/package/@elenajs/plugin-rollup-css) | ![stability-release-candidate](https://img.shields.io/badge/stability-pre--release-48c9b0.svg) |
50
- | [`@elenajs/ssr`](https://github.com/getelena/elena/tree/main/packages/ssr) | Elena server-side rendering tools. | [![npm](https://img.shields.io/npm/v/@elenajs/ssr.svg)](https://www.npmjs.com/package/@elenajs/ssr) | ![stability-experimental](https://img.shields.io/badge/stability-experimental-red.svg) |
51
- | [`@elenajs/mcp`](https://github.com/getelena/elena/tree/main/packages/ssr) | Elena MCP server. | [![npm](https://img.shields.io/npm/v/@elenajs/mcp.svg)](https://www.npmjs.com/package/@elenajs/mcp) | ![stability-experimental](https://img.shields.io/badge/stability-experimental-red.svg) |
53
+ class Stack extends Elena(HTMLElement) {
54
+ static tagName = "my-stack";
55
+ static props = ["direction"];
52
56
 
53
- <!-- https://github.com/mkenney/software-guides/blob/master/STABILITY-BADGES.md -->
57
+ direction = "column";
58
+ }
54
59
 
55
- ## Development
60
+ Stack.define();
61
+ ```
56
62
 
57
- For more details about pull requests, commit conventions and code style, please see [CONTRIBUTING.md](CONTRIBUTING.md).
63
+ **See the full documentation at [elenajs.com](https://elenajs.com).**
58
64
 
59
- ## License
65
+ ## Why was Elena created
66
+
67
+ Elena was created by [@arielle](https://arielsalminen.com/) after nearly a decade of building enterprise-scale design systems with web components. The recurring pain points were often similar: accessibility issues, server-side rendering, layout shifts, flash of invisible content, React Server Components, too much reliance on client side JavaScript, and compatibility with e.g. third party analytics tools.
68
+
69
+ Elena was built to solve these problems while staying grounded in web standards and what the platform natively provides. This is how [Progressive Web Components](https://arielsalminen.com/2026/progressive-web-components/) were born.
70
+
71
+ ## Why should I use Elena
60
72
 
61
- MIT
73
+ **Elena is built for teams creating component libraries and design systems.** If you need web components that work across multiple frameworks (such as [React](https://react.dev), [Next.js](https://nextjs.org), [Vue](https://vuejs.org), [Angular](https://angular.dev)), render HTML and CSS before JavaScript loads, and sidestep common issues like accessibility problems, SSR limitations, and layout shifts, Elena is built for exactly that.
62
74
 
63
- ## Copyright
75
+ It handles the cross-framework complexity (prop/attribute syncing, event delegation, framework compatibility) so you can focus on building components rather than plumbing.
76
+
77
+ ## Next steps
78
+
79
+ - Start with the [Quick Start](https://elenajs.com/start/) guide.
80
+ - View the [Live examples](https://elenajs.com/examples/) for demos.
81
+ - Try Elena in the [Playground](https://elenajs.com/playground/).
82
+ - Read how [Elena compares](https://elenajs.com/advanced/faq#how-does-elena-compare-against-other-tools) against other web component libraries.
83
+ - Browse our [FAQ](https://elenajs.com/advanced/faq) for frequently asked questions.
84
+
85
+ ## Provided tools
86
+
87
+ Elena is a monorepo containing several tools (13 in total!) published to npm under the `@elenajs` scope. These are the main tools intended for development:
88
+
89
+ | Package | Description | Version | Stability |
90
+ | --- | --- | --- | --- |
91
+ | [`@elenajs/core`](https://github.com/getelena/elena/tree/main/packages/core) | Elena core runtime library. | [![npm](https://img.shields.io/npm/v/@elenajs/core.svg)](https://www.npmjs.com/package/@elenajs/core) | ![stability-stable](https://img.shields.io/badge/stability-stable-green.svg) |
92
+ | [`@elenajs/components`](https://github.com/getelena/elena/tree/main/packages/components) | Elena demo web components. | [![npm](https://img.shields.io/npm/v/@elenajs/components.svg)](https://www.npmjs.com/package/@elenajs/components) | ![stability-stable](https://img.shields.io/badge/stability-stable-green.svg) |
93
+ | [`@elenajs/bundler`](https://github.com/getelena/elena/tree/main/packages/bundler) | Elena bundler for component libraries. | [![npm](https://img.shields.io/npm/v/@elenajs/bundler.svg)](https://www.npmjs.com/package/@elenajs/bundler) | ![stability-stable](https://img.shields.io/badge/stability-stable-green.svg) |
94
+ | [`@elenajs/cli`](https://github.com/getelena/elena/tree/main/packages/cli) | Elena CLI for scaffolding web components. | [![npm](https://img.shields.io/npm/v/@elenajs/cli.svg)](https://www.npmjs.com/package/@elenajs/cli) | ![stability-stable](https://img.shields.io/badge/stability-stable-green.svg) |
95
+ | [`@elenajs/ssr`](https://github.com/getelena/elena/tree/main/packages/ssr) | Elena server-side rendering tools. | [![npm](https://img.shields.io/npm/v/@elenajs/ssr.svg)](https://www.npmjs.com/package/@elenajs/ssr) | ![stability-experimental](https://img.shields.io/badge/stability-experimental-orange.svg) |
96
+ | [`@elenajs/mcp`](https://github.com/getelena/elena/tree/main/packages/ssr) | Elena MCP server. | [![npm](https://img.shields.io/npm/v/@elenajs/mcp.svg)](https://www.npmjs.com/package/@elenajs/mcp) | ![stability-experimental](https://img.shields.io/badge/stability-experimental-orange.svg) |
97
+
98
+ <!-- https://github.com/orangemug/stability-badges -->
99
+
100
+ ## License
64
101
 
65
- Copyright © 2026 [Ariel Salminen](https://arielsalminen.com)
102
+ Released under the MIT License. Copyright © 2025-2026 [Ariel Salminen](https://arielsalminen.com).
package/dist/bundle.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @elenajs/core v1.0.0-rc.7
2
+ * @elenajs/core v1.0.0
3
3
  * (c) 2025-present Ariel Salminen and Elena contributors
4
4
  * @license MIT
5
5
  */
6
- function t(t,s,e){if(s="boolean"===t&&"boolean"!=typeof s?null!==s:s,!e)return s;if("toAttribute"===e)switch(t){case"object":case"array":return null===s?null:JSON.stringify(s);case"boolean":return s?"":null;case"number":return null===s?null:s;default:return""===s?null:s}else switch(t){case"object":case"array":if(!s)return s;try{return JSON.parse(s)}catch{return console.warn("░█ [ELENA]: Invalid JSON: "+s),null}case"boolean":return s;case"number":return null!==s?+s:s;default:return s??""}}function s(t,s,e){t?null===e?t.removeAttribute(s):t.setAttribute(s,e):console.warn("░█ [ELENA]: Cannot sync attrs.")}const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function i(t){return Array.isArray(t)?t.map(t=>n(t)).join(""):n(t)}function n(t){return t?.t?String(t):(s=String(t??""),String(s).replace(/[&<>"']/g,t=>e[t]));var s}function o(t,...s){let e;return{t:!0,strings:t,values:s,toString:()=>(void 0===e&&(e=t.reduce((t,e,n)=>t+e+i(s[n]),"")),e)}}function r(t){return{t:!0,toString:()=>t??""}}const h=Object.freeze({t:!0,toString:()=>""}),c=t=>Array.isArray(t)?t.some(t=>t?.t):t?.t,u=t=>Array.isArray(t)?t.map(t=>String(t??"")).join(""):String(t??"");function l(t){return t.replace(/>\n\s*/g,">").replace(/\n\s*</g,"<").replace(/\n\s*/g," ").replace(/>\s+</g,"><")}const a=new WeakMap,f="e"+Math.random().toString(36).slice(2,6);function d(t,s,e){return!function(t,s,e){if(t.i!==s||!t.o)return!1;for(let s=0;s<e.length;s++){const i=e[s],n=Array.isArray(i)?u(i):i;if(n!==t.h[s]){if(c(i)||!t.o[s])return!1;t.h[s]=n,t.o[s].textContent=u(i)}}return!0}(t,s,e)&&(function(t,s,e){let n=a.get(s);if(!n){const t=Array.from(s,l);n={processedStrings:t,template:e.length>0?p(t,e.length):null},a.set(s,n)}if(n.template)t.o=function(t,s,e){const n=s.content.cloneNode(!0),o=document.createTreeWalker(n,NodeFilter.SHOW_COMMENT),r=new Array(e.length),h=[];let l;for(;l=o.nextNode();)l.data===f&&h.push(l);for(let t=0;t<h.length;t++){const s=e[t];if(c(s)){const e=document.createElement("template");e.innerHTML=i(s),h[t].parentNode.replaceChild(e.content,h[t])}else{const e=document.createTextNode(u(s));h[t].parentNode.replaceChild(e,h[t]),r[t]=e}}return t.replaceChildren(n),r}(t,n.template,e);else{const s=e.map(t=>i(t)),o=n.processedStrings.reduce((t,e,i)=>t+e+(s[i]??""),"").replace(/>\s+</g,"><").trim(),r=document.createElement("template");r.innerHTML=o,y(t,r.content.childNodes),t.o=null}t.i=s,t.h=e.map(t=>Array.isArray(t)?u(t):t)}(t,s,e),!0)}function p(t,s){const e=`\x3c!--${f}--\x3e`,i=t.reduce((t,i,n)=>t+i+(n<s?e:""),"").trim(),n=document.createElement("template");n.innerHTML=i;const o=document.createTreeWalker(n.content,NodeFilter.SHOW_COMMENT);let r=0;for(;o.nextNode();)o.currentNode.data===f&&r++;return r===s?n:null}function y(t,s){const e=Array.from(t.childNodes),i=Array.from(s),n=Math.max(e.length,i.length);for(let s=0;s<n;s++){const n=e[s],o=i[s];n?o?n.nodeType!==o.nodeType||n.nodeType===Node.ELEMENT_NODE&&n.tagName!==o.tagName?t.replaceChild(o,n):n.nodeType===Node.TEXT_NODE?n.textContent!==o.textContent&&(n.textContent=o.textContent):n.nodeType===Node.ELEMENT_NODE&&(g(n,o),y(n,o.childNodes)):t.removeChild(n):t.appendChild(o)}}function g(t,s){for(let e=t.attributes.length-1;e>=0;e--){const{name:i}=t.attributes[e];s.hasAttribute(i)||t.removeAttribute(i)}for(let e=0;e<s.attributes.length;e++){const{name:i,value:n}=s.attributes[e];t.getAttribute(i)!==n&&t.setAttribute(i,n)}}const b=new WeakSet;function m(e){return class extends e{element=null;attributeChangedCallback(s,e,i){super.attributeChangedCallback?.(s,e,i),"text"!==s?(this.u=!0,function(s,e,i,n){if(i!==n){const i=typeof s[e];"undefined"===i&&console.warn(`░█ [ELENA]: Prop "${e}" has no default.`);const o=t(i,n,"toProp");s[e]=o}}(this,s,e,i),this.u=!1,this.l&&e!==i&&!this.p&&this.m()):this.text=i??""}static get observedAttributes(){if(this.A)return this.A;const t=(this.props||[]).map(t=>"string"==typeof t?t:t.name);return this.A=[...t,"text"],this.A}connectedCallback(){super.connectedCallback?.(),this.S(),this.N(),this._(),this.v(),this.willUpdate(),this.C(),this.L(),this.k(),this.l||(this.l=!0,this.setAttribute("hydrated",""),this.firstUpdated()),this.updated()}S(){const e=this.constructor;if(b.has(e))return;const i=new Set,n=[];if(e.props){for(const t of e.props)"string"==typeof t?n.push(t):(n.push(t.name),!1===t.reflect&&i.add(t.name));n.includes("text")&&console.warn('░█ [ELENA]: "text" is reserved.'),function(e,i,n){for(const o of i){const i=!n||!n.has(o);Object.defineProperty(e,o,{configurable:!0,enumerable:!0,get(){return this.O?this.O.get(o):void 0},set(e){if(this.O||(this.O=new Map),e!==this.O.get(o)&&(this.O.set(o,e),this.isConnected))if(i){if(!this.u){const i=t(typeof e,e,"toAttribute");s(this,o,i)}}else this.l&&!this.p&&this.m()}})}}(e.prototype,n,i)}if(e.j=n,e.P=i,e.M=e.events||null,e.M)for(const t of e.M)Object.prototype.hasOwnProperty.call(e.prototype,t)||(e.prototype[t]=function(...s){return this.element[t](...s)});var o;e.U=(o=e.element)?t=>t.querySelector(o):t=>t.firstElementChild,b.add(e)}N(){this.u=!0;for(const t of this.constructor.j)if(Object.prototype.hasOwnProperty.call(this,t)){const s=this[t];delete this[t],this[t]=s}this.u=!1}_(){this.l||void 0!==this.q||(this.text=this.textContent.trim())}get F(){return this.J??this.shadowRoot??this}v(){const t=this.constructor;if(!t.shadow)return;this.J||this.shadowRoot||(this.J=this.attachShadow({mode:t.shadow}));const s=this.J??this.shadowRoot;if(t.styles){if(!t.R){const s=Array.isArray(t.styles)?t.styles:[t.styles];t.R=s.map(t=>{if("string"==typeof t){const s=new CSSStyleSheet;return s.replaceSync(t),s}return t})}s.adoptedStyleSheets=t.R}}C(){const t=this.render();if(t&&t.strings){const s=this.F;if(d(s,t.strings,t.values)){const t=this.element;if(this.element=this.constructor.U(s),this.W&&t&&this.element!==t){const s=this.constructor.M;for(const e of s)t.removeEventListener(e,this),this.element.addEventListener(e,this)}}}if(!this.element){const t=this.F;this.element=this.constructor.U(t),this.element||(this.constructor.element&&console.warn("░█ [ELENA]: Element not found."),this.element=t.firstElementChild)}}L(){if(this.O){const e=this.constructor.P;for(const[i,n]of this.O){if(e.has(i))continue;const o=t(typeof n,n,"toAttribute");(null!==o||this.hasAttribute(i))&&s(this,i,o)}}}k(){const t=this.constructor.M;if(!this.W&&t?.length)if(this.element){this.W=!0;for(const s of t)this.element.addEventListener(s,this)}else console.warn("░█ [ELENA]: Cannot add events.")}render(){}willUpdate(){}firstUpdated(){}updated(){}adoptedCallback(){super.adoptedCallback?.()}disconnectedCallback(){if(super.disconnectedCallback?.(),this.W){this.W=!1;for(const t of this.constructor.M)this.element?.removeEventListener(t,this)}}handleEvent(t){this.constructor.M?.includes(t.type)&&(t.bubbles&&(t.composed||this.F===this)||this.dispatchEvent(new Event(t.type,{bubbles:t.bubbles})))}get text(){return this.q??""}set text(t){const s=this.q;this.q=t,this.l&&s!==t&&!this.p&&this.m()}static define(){var t,s;this.tagName?(t=this.tagName,s=this,"undefined"!=typeof window&&"customElements"in window&&(window.customElements.get(t)||window.customElements.define(t,s))):console.warn("░█ [ELENA]: define() without a tagName.")}m(){this.p||this.$||(this.$=!0,this.D=new Promise(t=>{this.I=t}),queueMicrotask(()=>{try{this.T()}catch(t){console.error("░█ [ELENA]:",t)}}))}T(){this.$=!1;const t=this.I;this.I=null;try{try{this.willUpdate(),this.p=!0,this.C()}finally{this.p=!1}this.updated()}finally{this.D=null,t()}}get updateComplete(){return this.D?this.D:Promise.resolve()}requestUpdate(){this.l&&!this.p&&this.m()}}}export{m as Elena,o as html,h as nothing,r as unsafeHTML};
6
+ const t="░█ [ELENA]: ",s=Array.isArray,i=Symbol("elena.raw"),n=s=>console.warn(t+s),e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function o(t){return s(t)?t.map(r).join(""):r(t)}function r(t){return t?.[i]?String(t):String(t??"").replace(/[&<>"']/g,t=>e[t])}class h{constructor(t,s){this.strings=t,this.values=s}toString(){return null==this.t&&(this.t=this.strings.reduce((t,s,i)=>t+s+o(this.values[i]),"")),this.t}}function c(t,...s){return new h(t,s)}function l(t){return{[i]:!0,toString:()=>t??""}}h.prototype[i]=!0;const u={[i]:!0,toString:()=>""},f=t=>s(t)?t.some(t=>t?.[i]):!!t?.[i],a=t=>s(t)?t.join(""):String(t??"");function d(t){return t.replace(/(>)\n\s*|\n\s*(<)/g,"$1$2").replace(/\n\s*/g," ").replace(/>\s+</g,"><")}function p(t,s,i){if(s="boolean"===t&&"boolean"!=typeof s?null!==s:s,!i)return s;if("toAttribute"===i)switch(t){case"object":case"array":return s&&JSON.stringify(s);case"boolean":return s?"":null;default:return""===s?null:s}else switch(t){case"object":case"array":if(!s)return s;try{return JSON.parse(s)}catch{return n("Invalid JSON: "+s),null}case"number":return null!==s?+s:s;default:return s??""}}function g(t,s,i){t?null===i?t.removeAttribute(s):t.setAttribute(s,i):n("Cannot sync attrs.")}const y=new WeakMap,b="e"+Math.random().toString(36).slice(2),S=()=>document.createElement("template"),m=t=>document.createTreeWalker(t,128);function _(t,s){const i=`\x3c!--${b}--\x3e`,n=[];let e="";for(let o=0;o<t.length;o++)if(e+=t[o],o<s){const s=t[o].match(/([^\s"'>/=]+)\s*=\s*["']$/);s?(n.push(s[1]),e+=b+"_"+o):(n.push(null),e+=i)}const o=S();o.innerHTML=e.trim();const r=m(o.content);let h=0;for(;r.nextNode();)r.currentNode.data===b&&h++;return h!==n.filter(t=>null===t).length?null:{i:o,o:n}}function w(t,s){const i=Array.from(t.childNodes),n=Array.from(s),e=Math.max(i.length,n.length);for(let s=0;s<e;s++){const e=i[s],o=n[s];e?o?e.nodeType!==o.nodeType||1===e.nodeType&&e.tagName!==o.tagName?t.replaceChild(o,e):3===e.nodeType?e.textContent!==o.textContent&&(e.textContent=o.textContent):1===e.nodeType&&(v(e,o),w(e,o.childNodes)):t.removeChild(e):t.appendChild(o)}}function v(t,s){for(let i=t.attributes.length-1;i>=0;i--){const{name:n}=t.attributes[i];s.hasAttribute(n)||t.removeAttribute(n)}for(let i=0;i<s.attributes.length;i++){const{name:n,value:e}=s.attributes[i];t.getAttribute(n)!==e&&t.setAttribute(n,e)}}const x=new WeakSet,C=(t,s)=>Object.prototype.hasOwnProperty.call(t,s);function A(i){return class extends i{element=null;attributeChangedCallback(t,s,i){if(super.attributeChangedCallback?.(t,s,i),"text"!==t){if(s!==i)if(this.h&&!this.l){const s=this.u.get(t),n=typeof s,e="string"===n?i??"":p(n,i,"toProp");e!==s&&this.u.set(t,e),this.p()}else this.S=!0,function(t,s,i,e){if(i!==e){const i=typeof t[s];"undefined"===i&&n(`Prop "${s}" has no default.`);const o=p(i,e,"toProp");t[s]=o}}(this,t,s,i),this.S=!1}else this.text=i??""}static get observedAttributes(){if(this.m)return this.m;const t=(this.props||[]).map(t=>"string"==typeof t?t:t.name);return this.m=[...t,"text"],this.m}connectedCallback(){super.connectedCallback?.(),this._(),this.v(),this.h||void 0!==this.C||(this.text=this.textContent.trim()),this.A(),this.k=this.P??this.shadowRoot??this,this.$??=()=>{try{this.M()}catch(s){console.error(t,s)}},this.willUpdate(),this.N(),this.O(),this.j(),this.h||(this.h=!0,this.setAttribute("hydrated",""),this.firstUpdated()),this.updated()}_(){const t=this.constructor;if(x.has(t))return;const s=new Set,i=[];if(t.props){for(const n of t.props)"string"==typeof n?i.push(n):(i.push(n.name),!1===n.reflect&&s.add(n.name));i.includes("text")&&n('"text" is reserved.'),function(t,s,i){for(const n of s){const s=!i||!i.has(n);Object.defineProperty(t,n,{configurable:!0,enumerable:!0,get(){return this.u?.get(n)},set(t){if(this.u||(this.u=new Map),t!==this.u.get(n)&&(this.u.set(n,t),this.isConnected))if(s){if(!this.S){const s=p(typeof t,t,"toAttribute");g(this,n,s)}}else this.h&&!this.l&&this.p()}})}}(t.prototype,i,s)}if(t.U=i,t.q=s,t.J=t.events||null,t.J)for(const s of t.J)C(t.prototype,s)||(t.prototype[s]=function(...t){return this.element[s](...t)});var e;t.R=(e=t.element)?t=>t.querySelector(e):t=>t.firstElementChild,x.add(t)}v(){this.S=!0;for(const t of this.constructor.U)if(C(this,t)){const s=this[t];delete this[t],this[t]=s}this.S=!1}A(){const t=this.constructor;if(!t.shadow)return;if(!this.P&&!this.shadowRoot){const s={mode:t.shadow};t.registry&&(s.customElementRegistry=t.registry),this.P=this.attachShadow(s)}const s=this.P??this.shadowRoot;if(t.styles){if(!t.W){const s=[t.styles].flat();t.W=s.map(t=>{if("string"==typeof t){const s=new CSSStyleSheet;return s.replaceSync(t),s}return t})}s.adoptedStyleSheets=t.W}}N(){const t=this.constructor,i=this.k,e=this.render();if(e&&e.strings&&!function(t,i,n){if(t.D!==i||!t.F)return!1;const e=t.F,o=t.I;for(let t=0;t<n.length;t++){const i=n[t],r=s(i)?a(i):i;if(r===o[t])continue;if(f(i)&&i!==u)return!1;const h=e[t];if(!h)return!1;o[t]=r;const c=String(r??"");h.nodeType?h.textContent=c:h[0].setAttribute(h[1],c)}return!0}(r=i,h=e.strings,c=e.values)&&(function(t,i,n){let e=y.get(i);if(!e){const t=i.map(d);e={L:t,T:n.length>0?_(t,n.length):null},y.set(i,e)}if(e.T)t.F=function(t,i,n){const{i:e,o:r}=i,h=e.content.cloneNode(!0),c=m(h),l=Array(n.length),d=[];let p;for(;p=c.nextNode();)p.data===b&&d.push(p);let g=0;for(let t=0;t<n.length;t++){const i=r[t];if(i){const e=h.querySelector(`[${i}="${b+"_"+t}"]`);if(e){const o=n[t],r=String((s(o)?a(o):o)??"");e.setAttribute(i,r),l[t]=[e,i]}}else{const s=d[g++],i=n[t];if(f(i)&&i!==u){const t=S();t.innerHTML=o(i),s.parentNode.replaceChild(t.content,s)}else{const n=document.createTextNode(a(i));s.parentNode.replaceChild(n,s),l[t]=n}}}return t.D?(w(t,h.childNodes),null):(t.replaceChildren(h),l)}(t,e.T,n);else{const s=n.map(o),i=e.L.reduce((t,i,n)=>t+i+(s[n]??""),"").replace(/>\s+</g,"><").trim(),r=S();r.innerHTML=i,w(t,r.content.childNodes),t.F=null}t.D=i,t.I=n.map(t=>s(t)?a(t):t)}(r,h,c),1)){const s=this.element;if(this.element=t.R(i),this.B&&s&&this.element!==s){const i=t.J;for(const t of i)s.removeEventListener(t,this),this.element.addEventListener(t,this)}}var r,h,c;this.element||(this.element=t.R(i),this.element||(t.element&&n("Element not found."),this.element=i.firstElementChild))}O(){if(this.u){const t=this.constructor.q;for(const[s,i]of this.u){if(t.has(s))continue;const n=p(typeof i,i,"toAttribute");(null!==n||this.hasAttribute(s))&&g(this,s,n)}}}j(){const t=this.constructor.J;if(!this.B&&t?.length)if(this.element){this.B=!0;for(const s of t)this.element.addEventListener(s,this)}else n("Cannot add events.")}render(){}willUpdate(){}firstUpdated(){}updated(){}adoptedCallback(){super.adoptedCallback?.()}disconnectedCallback(){if(super.disconnectedCallback?.(),this.B){this.B=!1;for(const t of this.constructor.J)this.element?.removeEventListener(t,this)}}handleEvent(t){this.constructor.J?.includes(t.type)&&(t.bubbles&&(t.composed||this.k===this)||this.dispatchEvent(new Event(t.type,{bubbles:t.bubbles})))}get text(){return this.C??""}set text(t){const s=this.C;this.C=t,this.h&&s!==t&&!this.l&&this.p()}static define(t){const s=this.tagName;s?function(t,s,i){const n=i??globalThis.customElements;n?.get(t)||n?.define(t,s)}(s,this,t):n("define() without a tagName.")}p(){this.l||this.G||(this.G=!0,queueMicrotask(this.$))}M(){this.G=!1;const t=this.H;this.H=null;try{try{this.willUpdate(),this.l=!0,this.N()}finally{this.l=!1}this.updated()}finally{this.K=null,t?.()}}get updateComplete(){return this.G?(this.K||(this.K=new Promise(t=>{this.H=t})),this.K):Promise.resolve()}requestUpdate(){this.h&&!this.l&&this.p()}}}export{A as Elena,c as html,u as nothing,l as unsafeHTML};
@@ -19,11 +19,11 @@ export function syncAttribute(element: Element, name: string, value: string | nu
19
19
  * at class-creation time. Values are stored per-instance
20
20
  * via a `_props` Map that is lazily created.
21
21
  *
22
- * @param {Function} proto - The class prototype
22
+ * @param {Object} proto - The class prototype
23
23
  * @param {string[]} propNames - Prop names to define
24
24
  * @param {Set<string>} [noReflect] - Props that should not reflect to attributes
25
25
  */
26
- export function setProps(proto: Function, propNames: string[], noReflect?: Set<string>): void;
26
+ export function setProps(proto: Object, propNames: string[], noReflect?: Set<string>): void;
27
27
  /**
28
28
  * We need to update the internals of the Elena Element
29
29
  * when props on the host element are changed.
@@ -1 +1 @@
1
- {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../src/common/props.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,mCAJW,MAAM,SACN,GAAG,cACH,aAAa,GAAG,QAAQ,OAwClC;AAED;;;;;;GAMG;AACH,uCAJW,OAAO,QACP,MAAM,SACN,MAAM,GAAG,IAAI,QAYvB;AAED;;;;;;;;GAQG;AACH,qDAHW,MAAM,EAAE,cACR,GAAG,CAAC,MAAM,CAAC,QAsCrB;AAED;;;;;;;;GAQG;AACH,kCALW,MAAM,QACN,MAAM,YACN,GAAG,YACH,GAAG,QAWb"}
1
+ {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../src/common/props.js"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,mCAJW,MAAM,SACN,GAAG,cACH,aAAa,GAAG,QAAQ,OAqClC;AAED;;;;;;GAMG;AACH,uCAJW,OAAO,QACP,MAAM,SACN,MAAM,GAAG,IAAI,QAYvB;AAED;;;;;;;;GAQG;AACH,gCAJW,MAAM,aACN,MAAM,EAAE,cACR,GAAG,CAAC,MAAM,CAAC,QAsCrB;AAED;;;;;;;;GAQG;AACH,kCALW,MAAM,QACN,MAAM,YACN,GAAG,YACH,GAAG,QAWb"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Render a tagged template into an Elena Element with DOM diffing.
3
- * Returns true if the DOM was fully rebuilt, false if only text
4
- * nodes were patched in place.
3
+ * Returns true if the DOM was fully rebuilt, false if parts were
4
+ * patched in place.
5
5
  *
6
6
  * @param {HTMLElement} element
7
7
  * @param {TemplateStringsArray} strings - Static parts of the tagged template
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/common/render.js"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,wCALW,WAAW,WACX,oBAAoB,kBAElB,OAAO,CAQnB"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/common/render.js"],"names":[],"mappings":"AAWA;;;;;;;;;GASG;AACH,wCALW,WAAW,WACX,oBAAoB,kBAElB,OAAO,CAQnB"}
@@ -4,7 +4,7 @@
4
4
  * @param {string} tagName
5
5
  * @param {Function} Element
6
6
  */
7
- export function defineElement(tagName: string, Element: Function): void;
7
+ export function defineElement(tagName: string, Element: Function, registry: any): void;
8
8
  export function escapeHtml(str: any): string;
9
9
  /**
10
10
  * Resolve an interpolated template value to its
@@ -20,10 +20,9 @@ export function resolveValue(value: any): string;
20
20
  *
21
21
  * @param {TemplateStringsArray} strings
22
22
  * @param {...*} values
23
- * @returns {{ __raw: true, strings: TemplateStringsArray, values: Array, toString(): string }}
23
+ * @returns {{ strings: TemplateStringsArray, values: Array, toString(): string }}
24
24
  */
25
25
  export function html(strings: TemplateStringsArray, ...values: any[]): {
26
- __raw: true;
27
26
  strings: TemplateStringsArray;
28
27
  values: any[];
29
28
  toString(): string;
@@ -32,10 +31,9 @@ export function html(strings: TemplateStringsArray, ...values: any[]): {
32
31
  * Renders a string as HTML rather than text.
33
32
  *
34
33
  * @param {string} str - The raw HTML string to trust.
35
- * @returns {{ __raw: true, toString(): string }}
34
+ * @returns {{ toString(): string }}
36
35
  */
37
36
  export function unsafeHTML(str: string): {
38
- __raw: true;
39
37
  toString(): string;
40
38
  };
41
39
  /**
@@ -45,16 +43,18 @@ export function unsafeHTML(str: string): {
45
43
  * @returns {string}
46
44
  */
47
45
  export function collapseWhitespace(string: string): string;
46
+ export function warn(msg: string): void;
48
47
  /**
49
48
  * A placeholder you can return from a conditional expression
50
49
  * inside a template to render nothing.
51
50
  *
52
- * @type {{ __raw: true, toString(): string }}
51
+ * @type {{ toString(): string }}
53
52
  */
54
53
  export const nothing: {
55
- __raw: true;
56
54
  toString(): string;
57
55
  };
58
56
  export function isRaw(value: any): boolean;
59
57
  export function toPlainText(value: any): string;
58
+ export const prefix: "\u2591\u2588 [ELENA]: ";
59
+ export const isArray: (arg: any) => arg is any[];
60
60
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/common/utils.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,uCAHW,MAAM,2BAShB;AASD,6CAEC;AAED;;;;;;GAMG;AACH,oCAHW,GAAC,GACC,MAAM,CAOlB;AAaD;;;;;;;GAOG;AACH,8BAJW,oBAAoB,aACjB,GAAC,EAAA,GACF;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAC;IAAC,MAAM,QAAQ;IAAC,QAAQ,IAAI,MAAM,CAAA;CAAE,CAiB7F;AAED;;;;;GAKG;AACH,gCAHW,MAAM,GACJ;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,IAAI,MAAM,CAAA;CAAE,CAI/C;AA4BD;;;;;GAKG;AACH,2CAHW,MAAM,GACJ,MAAM,CAQlB;AAtCD;;;;;GAKG;AACH,sBAFU;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,IAAI,MAAM,CAAA;CAAE,CAE6B;AAQnE,6BAHI,GAAC,GACC,OAAO,CAGmD;AAQhE,mCAHI,GAAC,GACC,MAAM,CAG0E"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/common/utils.js"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,uCAHW,MAAM,0CAMhB;AASD,6CAEC;AAED;;;;;;GAMG;AACH,oCAHW,GAAC,GACC,MAAM,CAOlB;AAkCD;;;;;;;GAOG;AACH,8BAJW,oBAAoB,aACjB,GAAC,EAAA,GACF;IAAE,OAAO,EAAE,oBAAoB,CAAC;IAAC,MAAM,QAAQ;IAAC,QAAQ,IAAI,MAAM,CAAA;CAAE,CAIhF;AAED;;;;;GAKG;AACH,gCAHW,MAAM,GACJ;IAAE,QAAQ,IAAI,MAAM,CAAA;CAAE,CAIlC;AA0BD;;;;;GAKG;AACH,2CAHW,MAAM,GACJ,MAAM,CAOlB;AAhIM,0BAHI,MAAM,QAGoC;AA6FrD;;;;;GAKG;AACH,sBAFU;IAAE,QAAQ,IAAI,MAAM,CAAA;CAAE,CAE2B;AAQpD,6BAHI,GAAC,GACC,OAAO,CAE6E;AAQ1F,mCAHI,GAAC,GACC,MAAM,CAEwE;AA3H3F,qBAAe,wBAAc,CAAC;AAC9B,iDAA8B"}
package/dist/elena.d.ts CHANGED
@@ -13,19 +13,23 @@ export type ElenaConstructor = new (...args: any[]) => HTMLElement;
13
13
  export type ElenaInstanceMembers = {
14
14
  text: string;
15
15
  element: HTMLElement | null;
16
+ updateComplete: Promise<void>;
16
17
  render(): void;
17
18
  willUpdate(): void;
18
19
  firstUpdated(): void;
19
20
  updated(): void;
21
+ requestUpdate(): void;
20
22
  connectedCallback(): void;
21
23
  disconnectedCallback(): void;
24
+ adoptedCallback(): void;
25
+ attributeChangedCallback(prop: string, oldValue: string | null, newValue: string | null): void;
22
26
  };
23
27
  export type ElenaPropObject = {
24
28
  name: string;
25
29
  reflect?: boolean;
26
30
  };
27
31
  export type ElenaElementConstructor = (new (...args: any[]) => HTMLElement & ElenaInstanceMembers) & {
28
- define(): void;
32
+ define(registry?: CustomElementRegistry): void;
29
33
  readonly observedAttributes: string[];
30
34
  tagName?: string;
31
35
  props?: (string | ElenaPropObject)[];
@@ -33,6 +37,7 @@ export type ElenaElementConstructor = (new (...args: any[]) => HTMLElement & Ele
33
37
  element?: string;
34
38
  shadow?: "open" | "closed";
35
39
  styles?: CSSStyleSheet | string | (CSSStyleSheet | string)[];
40
+ registry?: CustomElementRegistry;
36
41
  };
37
42
  import { html } from "./common/utils.js";
38
43
  import { unsafeHTML } from "./common/utils.js";
@@ -1 +1 @@
1
- {"version":3,"file":"elena.d.ts","sourceRoot":"","sources":["../src/elena.js"],"names":[],"mappings":"AAiEA;;;;;;;;;GASG;AACH,kCAHW,gBAAgB,GACd,uBAAuB,CAwenC;+BA3gBY,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,WAAW;mCAInC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAAC,MAAM,IAAI,IAAI,CAAC;IAAC,UAAU,IAAI,IAAI,CAAC;IAAC,YAAY,IAAI,IAAI,CAAC;IAAC,OAAO,IAAI,IAAI,CAAC;IAAC,iBAAiB,IAAI,IAAI,CAAC;IAAC,oBAAoB,IAAI,IAAI,CAAA;CAAE;8BAIjL;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE;sCAInC,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,WAAW,GAAG,oBAAoB,CAAC,GAAG;IACvE,MAAM,IAAI,IAAI,CAAC;IACnB,QAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC3B,MAAM,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,CAAC,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC;CAC9D;qBA5CqD,mBAAmB;2BAAnB,mBAAmB;wBAAnB,mBAAmB"}
1
+ {"version":3,"file":"elena.d.ts","sourceRoot":"","sources":["../src/elena.js"],"names":[],"mappings":"AAmEA;;;;;;;;;GASG;AACH,kCAHW,gBAAgB,GACd,uBAAuB,CAgfnC;+BArhBY,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,WAAW;mCAInC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAAC,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,MAAM,IAAI,IAAI,CAAC;IAAC,UAAU,IAAI,IAAI,CAAC;IAAC,YAAY,IAAI,IAAI,CAAC;IAAC,OAAO,IAAI,IAAI,CAAC;IAAC,aAAa,IAAI,IAAI,CAAC;IAAC,iBAAiB,IAAI,IAAI,CAAC;IAAC,oBAAoB,IAAI,IAAI,CAAC;IAAC,eAAe,IAAI,IAAI,CAAC;IAAC,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;CAAE;8BAIhW;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE;sCAInC,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,WAAW,GAAG,oBAAoB,CAAC,GAAG;IACvE,MAAM,CAAC,QAAQ,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACnD,QAAY,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC3B,MAAM,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,CAAC,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC;IAC7D,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;qBA7CmE,mBAAmB;2BAAnB,mBAAmB;wBAAnB,mBAAmB"}
package/dist/elena.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @elenajs/core v1.0.0-rc.7
2
+ * @elenajs/core v1.0.0
3
3
  * (c) 2025-present Ariel Salminen and Elena contributors
4
4
  * @license MIT
5
5
  */
6
- import{getProps as t,setProps as e,getPropValue as s,syncAttribute as n}from"./props.js";import{defineElement as i}from"./utils.js";export{html,nothing,unsafeHTML}from"./utils.js";import{renderTemplate as r}from"./render.js";const o=new WeakSet;function h(h){return class extends h{element=null;attributeChangedCallback(e,s,n){super.attributeChangedCallback?.(e,s,n),"text"!==e?(this._syncing=!0,t(this,e,s,n),this._syncing=!1,this._hydrated&&s!==n&&!this._isRendering&&this._safeRender()):this.text=n??""}static get observedAttributes(){if(this._observedAttrs)return this._observedAttrs;const t=(this.props||[]).map(t=>"string"==typeof t?t:t.name);return this._observedAttrs=[...t,"text"],this._observedAttrs}connectedCallback(){super.connectedCallback?.(),this._setupStaticProps(),this._captureClassFieldDefaults(),this._captureText(),this._attachShadow(),this.willUpdate(),this._applyRender(),this._syncProps(),this._delegateEvents(),this._hydrated||(this._hydrated=!0,this.setAttribute("hydrated",""),this.firstUpdated()),this.updated()}_setupStaticProps(){const t=this.constructor;if(o.has(t))return;const s=new Set,n=[];if(t.props){for(const e of t.props)"string"==typeof e?n.push(e):(n.push(e.name),!1===e.reflect&&s.add(e.name));n.includes("text")&&console.warn('░█ [ELENA]: "text" is reserved.'),e(t.prototype,n,s)}if(t._propNames=n,t._noReflect=s,t._elenaEvents=t.events||null,t._elenaEvents)for(const e of t._elenaEvents)Object.prototype.hasOwnProperty.call(t.prototype,e)||(t.prototype[e]=function(...t){return this.element[e](...t)});var i;t._resolver=(i=t.element)?t=>t.querySelector(i):t=>t.firstElementChild,o.add(t)}_captureClassFieldDefaults(){this._syncing=!0;for(const t of this.constructor._propNames)if(Object.prototype.hasOwnProperty.call(this,t)){const e=this[t];delete this[t],this[t]=e}this._syncing=!1}_captureText(){this._hydrated||void 0!==this._text||(this.text=this.textContent.trim())}get _renderRoot(){return this._shadow??this.shadowRoot??this}_attachShadow(){const t=this.constructor;if(!t.shadow)return;this._shadow||this.shadowRoot||(this._shadow=this.attachShadow({mode:t.shadow}));const e=this._shadow??this.shadowRoot;if(t.styles){if(!t._adoptedSheets){const e=Array.isArray(t.styles)?t.styles:[t.styles];t._adoptedSheets=e.map(t=>{if("string"==typeof t){const e=new CSSStyleSheet;return e.replaceSync(t),e}return t})}e.adoptedStyleSheets=t._adoptedSheets}}_applyRender(){const t=this.render();if(t&&t.strings){const e=this._renderRoot;if(r(e,t.strings,t.values)){const t=this.element;if(this.element=this.constructor._resolver(e),this._events&&t&&this.element!==t){const e=this.constructor._elenaEvents;for(const s of e)t.removeEventListener(s,this),this.element.addEventListener(s,this)}}}if(!this.element){const t=this._renderRoot;this.element=this.constructor._resolver(t),this.element||(this.constructor.element&&console.warn("░█ [ELENA]: Element not found."),this.element=t.firstElementChild)}}_syncProps(){if(this._props){const t=this.constructor._noReflect;for(const[e,i]of this._props){if(t.has(e))continue;const r=s(typeof i,i,"toAttribute");(null!==r||this.hasAttribute(e))&&n(this,e,r)}}}_delegateEvents(){const t=this.constructor._elenaEvents;if(!this._events&&t?.length)if(this.element){this._events=!0;for(const e of t)this.element.addEventListener(e,this)}else console.warn("░█ [ELENA]: Cannot add events.")}render(){}willUpdate(){}firstUpdated(){}updated(){}adoptedCallback(){super.adoptedCallback?.()}disconnectedCallback(){if(super.disconnectedCallback?.(),this._events){this._events=!1;for(const t of this.constructor._elenaEvents)this.element?.removeEventListener(t,this)}}handleEvent(t){this.constructor._elenaEvents?.includes(t.type)&&(t.bubbles&&(t.composed||this._renderRoot===this)||this.dispatchEvent(new Event(t.type,{bubbles:t.bubbles})))}get text(){return this._text??""}set text(t){const e=this._text;this._text=t,this._hydrated&&e!==t&&!this._isRendering&&this._safeRender()}static define(){this.tagName?i(this.tagName,this):console.warn("░█ [ELENA]: define() without a tagName.")}_safeRender(){this._isRendering||this._renderPending||(this._renderPending=!0,this._updateComplete=new Promise(t=>{this._resolveUpdate=t}),queueMicrotask(()=>{try{this._performUpdate()}catch(t){console.error("░█ [ELENA]:",t)}}))}_performUpdate(){this._renderPending=!1;const t=this._resolveUpdate;this._resolveUpdate=null;try{try{this.willUpdate(),this._isRendering=!0,this._applyRender()}finally{this._isRendering=!1}this.updated()}finally{this._updateComplete=null,t()}}get updateComplete(){return this._updateComplete?this._updateComplete:Promise.resolve()}requestUpdate(){this._hydrated&&!this._isRendering&&this._safeRender()}}}export{h as Elena};
6
+ import{getPropValue as t,getProps as e,setProps as s,syncAttribute as i}from"./props.js";import{prefix as n,warn as r,defineElement as o}from"./utils.js";export{html,nothing,unsafeHTML}from"./utils.js";import{renderTemplate as h}from"./render.js";const a=new WeakSet,d=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);function l(l){return class extends l{element=null;attributeChangedCallback(s,i,n){if(super.attributeChangedCallback?.(s,i,n),"text"!==s){if(i!==n)if(this._hydrated&&!this._isRendering){const e=this._props.get(s),i=typeof e,r="string"===i?n??"":t(i,n,"toProp");r!==e&&this._props.set(s,r),this._safeRender()}else this._syncing=!0,e(this,s,i,n),this._syncing=!1}else this.text=n??""}static get observedAttributes(){if(this._observedAttrs)return this._observedAttrs;const t=(this.props||[]).map(t=>"string"==typeof t?t:t.name);return this._observedAttrs=[...t,"text"],this._observedAttrs}connectedCallback(){super.connectedCallback?.(),this._setupStaticProps(),this._captureClassFieldDefaults(),this._hydrated||void 0!==this._text||(this.text=this.textContent.trim()),this._attachShadow(),this._root=this._shadow??this.shadowRoot??this,this._runUpdate??=()=>{try{this._performUpdate()}catch(t){console.error(n,t)}},this.willUpdate(),this._applyRender(),this._syncProps(),this._delegateEvents(),this._hydrated||(this._hydrated=!0,this.setAttribute("hydrated",""),this.firstUpdated()),this.updated()}_setupStaticProps(){const t=this.constructor;if(a.has(t))return;const e=new Set,i=[];if(t.props){for(const s of t.props)"string"==typeof s?i.push(s):(i.push(s.name),!1===s.reflect&&e.add(s.name));i.includes("text")&&r('"text" is reserved.'),s(t.prototype,i,e)}if(t._propNames=i,t._noReflect=e,t._elenaEvents=t.events||null,t._elenaEvents)for(const e of t._elenaEvents)d(t.prototype,e)||(t.prototype[e]=function(...t){return this.element[e](...t)});var n;t._resolver=(n=t.element)?t=>t.querySelector(n):t=>t.firstElementChild,a.add(t)}_captureClassFieldDefaults(){this._syncing=!0;for(const t of this.constructor._propNames)if(d(this,t)){const e=this[t];delete this[t],this[t]=e}this._syncing=!1}_attachShadow(){const t=this.constructor;if(!t.shadow)return;if(!this._shadow&&!this.shadowRoot){const e={mode:t.shadow};t.registry&&(e.customElementRegistry=t.registry),this._shadow=this.attachShadow(e)}const e=this._shadow??this.shadowRoot;if(t.styles){if(!t._adoptedSheets){const e=[t.styles].flat();t._adoptedSheets=e.map(t=>{if("string"==typeof t){const e=new CSSStyleSheet;return e.replaceSync(t),e}return t})}e.adoptedStyleSheets=t._adoptedSheets}}_applyRender(){const t=this.constructor,e=this._root,s=this.render();if(s&&s.strings&&h(e,s.strings,s.values)){const s=this.element;if(this.element=t._resolver(e),this._events&&s&&this.element!==s){const e=t._elenaEvents;for(const t of e)s.removeEventListener(t,this),this.element.addEventListener(t,this)}}this.element||(this.element=t._resolver(e),this.element||(t.element&&r("Element not found."),this.element=e.firstElementChild))}_syncProps(){if(this._props){const e=this.constructor._noReflect;for(const[s,n]of this._props){if(e.has(s))continue;const r=t(typeof n,n,"toAttribute");(null!==r||this.hasAttribute(s))&&i(this,s,r)}}}_delegateEvents(){const t=this.constructor._elenaEvents;if(!this._events&&t?.length)if(this.element){this._events=!0;for(const e of t)this.element.addEventListener(e,this)}else r("Cannot add events.")}render(){}willUpdate(){}firstUpdated(){}updated(){}adoptedCallback(){super.adoptedCallback?.()}disconnectedCallback(){if(super.disconnectedCallback?.(),this._events){this._events=!1;for(const t of this.constructor._elenaEvents)this.element?.removeEventListener(t,this)}}handleEvent(t){this.constructor._elenaEvents?.includes(t.type)&&(t.bubbles&&(t.composed||this._root===this)||this.dispatchEvent(new Event(t.type,{bubbles:t.bubbles})))}get text(){return this._text??""}set text(t){const e=this._text;this._text=t,this._hydrated&&e!==t&&!this._isRendering&&this._safeRender()}static define(t){const e=this.tagName;e?o(e,this,t):r("define() without a tagName.")}_safeRender(){this._isRendering||this._renderPending||(this._renderPending=!0,queueMicrotask(this._runUpdate))}_performUpdate(){this._renderPending=!1;const t=this._resolveUpdate;this._resolveUpdate=null;try{try{this.willUpdate(),this._isRendering=!0,this._applyRender()}finally{this._isRendering=!1}this.updated()}finally{this._updateComplete=null,t?.()}}get updateComplete(){return this._renderPending?(this._updateComplete||(this._updateComplete=new Promise(t=>{this._resolveUpdate=t})),this._updateComplete):Promise.resolve()}requestUpdate(){this._hydrated&&!this._isRendering&&this._safeRender()}}}export{l as Elena};
package/dist/props.js CHANGED
@@ -1 +1 @@
1
- function t(t,e,n){if(e="boolean"===t&&"boolean"!=typeof e?null!==e:e,!n)return e;if("toAttribute"===n)switch(t){case"object":case"array":return null===e?null:JSON.stringify(e);case"boolean":return e?"":null;case"number":return null===e?null:e;default:return""===e?null:e}else switch(t){case"object":case"array":if(!e)return e;try{return JSON.parse(e)}catch{return console.warn("░█ [ELENA]: Invalid JSON: "+e),null}case"boolean":return e;case"number":return null!==e?+e:e;default:return e??""}}function e(t,e,n){t?null===n?t.removeAttribute(e):t.setAttribute(e,n):console.warn("░█ [ELENA]: Cannot sync attrs.")}function n(n,r,s){for(const o of r){const r=!s||!s.has(o);Object.defineProperty(n,o,{configurable:!0,enumerable:!0,get(){return this._props?this._props.get(o):void 0},set(n){if(this._props||(this._props=new Map),n!==this._props.get(o)&&(this._props.set(o,n),this.isConnected))if(r){if(!this._syncing){const r=t(typeof n,n,"toAttribute");e(this,o,r)}}else this._hydrated&&!this._isRendering&&this._safeRender()}})}}function r(e,n,r,s){if(r!==s){const r=typeof e[n];"undefined"===r&&console.warn(`░█ [ELENA]: Prop "${n}" has no default.`);const o=t(r,s,"toProp");e[n]=o}}export{t as getPropValue,r as getProps,n as setProps,e as syncAttribute};
1
+ import{warn as t}from"./utils.js";function e(e,n,r){if(n="boolean"===e&&"boolean"!=typeof n?null!==n:n,!r)return n;if("toAttribute"===r)switch(e){case"object":case"array":return n&&JSON.stringify(n);case"boolean":return n?"":null;default:return""===n?null:n}else switch(e){case"object":case"array":if(!n)return n;try{return JSON.parse(n)}catch{return t("Invalid JSON: "+n),null}case"number":return null!==n?+n:n;default:return n??""}}function n(e,n,r){e?null===r?e.removeAttribute(n):e.setAttribute(n,r):t("Cannot sync attrs.")}function r(t,r,s){for(const o of r){const r=!s||!s.has(o);Object.defineProperty(t,o,{configurable:!0,enumerable:!0,get(){return this._props?.get(o)},set(t){if(this._props||(this._props=new Map),t!==this._props.get(o)&&(this._props.set(o,t),this.isConnected))if(r){if(!this._syncing){const r=e(typeof t,t,"toAttribute");n(this,o,r)}}else this._hydrated&&!this._isRendering&&this._safeRender()}})}}function s(n,r,s,o){if(s!==o){const s=typeof n[r];"undefined"===s&&t(`Prop "${r}" has no default.`);const i=e(s,o,"toProp");n[r]=i}}export{e as getPropValue,s as getProps,r as setProps,n as syncAttribute};
package/dist/render.js CHANGED
@@ -1 +1 @@
1
- import{toPlainText as e,isRaw as t,collapseWhitespace as n,resolveValue as r}from"./utils.js";const o=new WeakMap,l="e"+Math.random().toString(36).slice(2,6);function a(a,i,d){return!function(n,r,o){if(n._tplStrings!==r||!n._tplParts)return!1;for(let r=0;r<o.length;r++){const l=o[r],a=Array.isArray(l)?e(l):l;if(a!==n._tplValues[r]){if(t(l)||!n._tplParts[r])return!1;n._tplValues[r]=a,n._tplParts[r].textContent=e(l)}}return!0}(a,i,d)&&(function(a,i,d){let u=o.get(i);if(!u){const e=Array.from(i,n);u={processedStrings:e,template:d.length>0?c(e,d.length):null},o.set(i,u)}if(u.template)a._tplParts=function(n,o,a){const c=o.content.cloneNode(!0),s=document.createTreeWalker(c,NodeFilter.SHOW_COMMENT),i=new Array(a.length),d=[];let u;for(;u=s.nextNode();)u.data===l&&d.push(u);for(let n=0;n<d.length;n++){const o=a[n];if(t(o)){const e=document.createElement("template");e.innerHTML=r(o),d[n].parentNode.replaceChild(e.content,d[n])}else{const t=document.createTextNode(e(o));d[n].parentNode.replaceChild(t,d[n]),i[n]=t}}return n.replaceChildren(c),i}(a,u.template,d);else{const e=d.map(e=>r(e)),t=u.processedStrings.reduce((t,n,r)=>t+n+(e[r]??""),"").replace(/>\s+</g,"><").trim(),n=document.createElement("template");n.innerHTML=t,s(a,n.content.childNodes),a._tplParts=null}a._tplStrings=i,a._tplValues=d.map(t=>Array.isArray(t)?e(t):t)}(a,i,d),!0)}function c(e,t){const n=`\x3c!--${l}--\x3e`,r=e.reduce((e,r,o)=>e+r+(o<t?n:""),"").trim(),o=document.createElement("template");o.innerHTML=r;const a=document.createTreeWalker(o.content,NodeFilter.SHOW_COMMENT);let c=0;for(;a.nextNode();)a.currentNode.data===l&&c++;return c===t?o:null}function s(e,t){const n=Array.from(e.childNodes),r=Array.from(t),o=Math.max(n.length,r.length);for(let t=0;t<o;t++){const o=n[t],l=r[t];o?l?o.nodeType!==l.nodeType||o.nodeType===Node.ELEMENT_NODE&&o.tagName!==l.tagName?e.replaceChild(l,o):o.nodeType===Node.TEXT_NODE?o.textContent!==l.textContent&&(o.textContent=l.textContent):o.nodeType===Node.ELEMENT_NODE&&(i(o,l),s(o,l.childNodes)):e.removeChild(o):e.appendChild(l)}}function i(e,t){for(let n=e.attributes.length-1;n>=0;n--){const{name:r}=e.attributes[n];t.hasAttribute(r)||e.removeAttribute(r)}for(let n=0;n<t.attributes.length;n++){const{name:r,value:o}=t.attributes[n];e.getAttribute(r)!==o&&e.setAttribute(r,o)}}export{a as renderTemplate};
1
+ import{isArray as t,toPlainText as e,isRaw as n,nothing as r,collapseWhitespace as o,resolveValue as l}from"./utils.js";const s=new WeakMap,a="e"+Math.random().toString(36).slice(2),c=()=>document.createElement("template"),i=t=>document.createTreeWalker(t,128);function u(u,m,f){return!function(o,l,s){if(o._templateStrings!==l||!o._templateParts)return!1;const a=o._templateParts,c=o._templateValues;for(let o=0;o<s.length;o++){const l=s[o],i=t(l)?e(l):l;if(i===c[o])continue;if(n(l)&&l!==r)return!1;const u=a[o];if(!u)return!1;c[o]=i;const p=String(i??"");u.nodeType?u.textContent=p:u[0].setAttribute(u[1],p)}return!0}(u,m,f)&&(function(u,m,f){let h=s.get(m);if(!h){const t=m.map(o);h={_strings:t,_template:f.length>0?p(t,f.length):null},s.set(m,h)}if(h._template)u._templateParts=function(o,s,u){const{_tpl:p,_attrs:m}=s,f=p.content.cloneNode(!0),h=i(f),g=Array(u.length),_=[];let N;for(;N=h.nextNode();)N.data===a&&_.push(N);let x=0;for(let o=0;o<u.length;o++){const s=m[o];if(s){const n=f.querySelector(`[${s}="${a+"_"+o}"]`);if(n){const r=u[o],l=String((t(r)?e(r):r)??"");n.setAttribute(s,l),g[o]=[n,s]}}else{const t=_[x++],s=u[o];if(n(s)&&s!==r){const e=c();e.innerHTML=l(s),t.parentNode.replaceChild(e.content,t)}else{const n=document.createTextNode(e(s));t.parentNode.replaceChild(n,t),g[o]=n}}}return o._templateStrings?(d(o,f.childNodes),null):(o.replaceChildren(f),g)}(u,h._template,f);else{const t=f.map(l),e=h._strings.reduce((e,n,r)=>e+n+(t[r]??""),"").replace(/>\s+</g,"><").trim(),n=c();n.innerHTML=e,d(u,n.content.childNodes),u._templateParts=null}u._templateStrings=m,u._templateValues=f.map(n=>t(n)?e(n):n)}(u,m,f),!0)}function p(t,e){const n=`\x3c!--${a}--\x3e`,r=[];let o="";for(let l=0;l<t.length;l++)if(o+=t[l],l<e){const e=t[l].match(/([^\s"'>/=]+)\s*=\s*["']$/);e?(r.push(e[1]),o+=a+"_"+l):(r.push(null),o+=n)}const l=c();l.innerHTML=o.trim();const s=i(l.content);let u=0;for(;s.nextNode();)s.currentNode.data===a&&u++;return u!==r.filter(t=>null===t).length?null:{_tpl:l,_attrs:r}}function d(t,e){const n=Array.from(t.childNodes),r=Array.from(e),o=Math.max(n.length,r.length);for(let e=0;e<o;e++){const o=n[e],l=r[e];o?l?o.nodeType!==l.nodeType||1===o.nodeType&&o.tagName!==l.tagName?t.replaceChild(l,o):3===o.nodeType?o.textContent!==l.textContent&&(o.textContent=l.textContent):1===o.nodeType&&(m(o,l),d(o,l.childNodes)):t.removeChild(o):t.appendChild(l)}}function m(t,e){for(let n=t.attributes.length-1;n>=0;n--){const{name:r}=t.attributes[n];e.hasAttribute(r)||t.removeAttribute(r)}for(let n=0;n<e.attributes.length;n++){const{name:r,value:o}=e.attributes[n];t.getAttribute(r)!==o&&t.setAttribute(r,o)}}export{u as renderTemplate};
package/dist/utils.js CHANGED
@@ -1 +1 @@
1
- function n(n,r){"undefined"!=typeof window&&"customElements"in window&&(window.customElements.get(n)||window.customElements.define(n,r))}const r={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function t(n){return String(n).replace(/[&<>"']/g,n=>r[n])}function e(n){return Array.isArray(n)?n.map(n=>i(n)).join(""):i(n)}function i(n){return n?.__raw?String(n):t(String(n??""))}function o(n,...r){let t;return{__raw:!0,strings:n,values:r,toString:()=>(void 0===t&&(t=n.reduce((n,t,i)=>n+t+e(r[i]),"")),t)}}function a(n){return{__raw:!0,toString:()=>n??""}}const u=Object.freeze({__raw:!0,toString:()=>""}),c=n=>Array.isArray(n)?n.some(n=>n?.__raw):n?.__raw,s=n=>Array.isArray(n)?n.map(n=>String(n??"")).join(""):String(n??"");function g(n){return n.replace(/>\n\s*/g,">").replace(/\n\s*</g,"<").replace(/\n\s*/g," ").replace(/>\s+</g,"><")}export{g as collapseWhitespace,n as defineElement,t as escapeHtml,o as html,c as isRaw,u as nothing,e as resolveValue,s as toPlainText,a as unsafeHTML};
1
+ const t="░█ [ELENA]: ",n=Array.isArray,r=Symbol("elena.raw"),s=n=>console.warn(t+n);function e(t,n,r){const s=r??globalThis.customElements;s?.get(t)||s?.define(t,n)}const o={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function i(t){return String(t).replace(/[&<>"']/g,t=>o[t])}function c(t){return n(t)?t.map(u).join(""):u(t)}function u(t){return t?.[r]?String(t):i(t??"")}class l{constructor(t,n){this.strings=t,this.values=n}toString(){return null==this._str&&(this._str=this.strings.reduce((t,n,r)=>t+n+c(this.values[r]),"")),this._str}}function a(t,...n){return new l(t,n)}function g(t){return{[r]:!0,toString:()=>t??""}}l.prototype[r]=!0;const p={[r]:!0,toString:()=>""},f=t=>n(t)?t.some(t=>t?.[r]):!!t?.[r],h=t=>n(t)?t.join(""):String(t??"");function S(t){return t.replace(/(>)\n\s*|\n\s*(<)/g,"$1$2").replace(/\n\s*/g," ").replace(/>\s+</g,"><")}export{S as collapseWhitespace,e as defineElement,i as escapeHtml,a as html,n as isArray,f as isRaw,p as nothing,t as prefix,c as resolveValue,h as toPlainText,g as unsafeHTML,s as warn};
package/package.json CHANGED
@@ -1,9 +1,21 @@
1
1
  {
2
2
  "name": "@elenajs/core",
3
- "version": "1.0.0-rc.7",
3
+ "version": "1.0.0",
4
4
  "description": "Elena is a simple, tiny library for building Progressive Web Components.",
5
5
  "author": "Elena <hi@elenajs.com>",
6
6
  "homepage": "https://elenajs.com/",
7
+ "keywords": [
8
+ "progressive web components",
9
+ "custom elements manifest",
10
+ "progressive enhancement",
11
+ "custom elements",
12
+ "web components",
13
+ "design system",
14
+ "javascript",
15
+ "typescript",
16
+ "elena",
17
+ "ssr"
18
+ ],
7
19
  "repository": {
8
20
  "type": "git",
9
21
  "url": "git+https://github.com/getelena/elena.git",
@@ -43,18 +55,18 @@
43
55
  "clean": "rm -rf dist/"
44
56
  },
45
57
  "devDependencies": {
46
- "@playwright/test": "1.58.2",
58
+ "@playwright/test": "1.59.1",
47
59
  "@rollup/plugin-terser": "1.0.0",
48
- "@vitest/browser": "4.1.0",
49
- "@vitest/browser-playwright": "4.1.0",
50
- "@vitest/coverage-v8": "4.1.0",
51
- "happy-dom": "20.8.4",
60
+ "@vitest/browser": "4.1.2",
61
+ "@vitest/browser-playwright": "4.1.2",
62
+ "@vitest/coverage-v8": "4.1.2",
63
+ "happy-dom": "20.8.9",
52
64
  "lit": "3.3.2",
53
- "rollup": "4.59.0",
65
+ "rollup": "4.60.1",
54
66
  "rollup-plugin-summary": "3.0.1",
55
67
  "serve": "14.2.6",
56
- "typescript": "5.9.3",
57
- "vitest": "4.1.0"
68
+ "typescript": "6.0.2",
69
+ "vitest": "4.1.2"
58
70
  },
59
- "gitHead": "d941d90c7a20055d154c2a946b289d9620765634"
71
+ "gitHead": "ef466853f84deb6559ea66b54cd85b7e043e9f36"
60
72
  }
@@ -1,3 +1,5 @@
1
+ import { warn } from "./utils.js";
2
+
1
3
  /**
2
4
  * Get the value of the Elena Element property.
3
5
  *
@@ -14,11 +16,10 @@ export function getPropValue(type, value, transform) {
14
16
  switch (type) {
15
17
  case "object":
16
18
  case "array":
17
- return value === null ? null : JSON.stringify(value);
19
+ return value && JSON.stringify(value);
18
20
  case "boolean":
19
21
  return value ? "" : null;
20
- case "number":
21
- return value === null ? null : value;
22
+ // number, string:
22
23
  default:
23
24
  return value === "" ? null : value;
24
25
  }
@@ -32,11 +33,9 @@ export function getPropValue(type, value, transform) {
32
33
  try {
33
34
  return JSON.parse(value);
34
35
  } catch {
35
- console.warn("░█ [ELENA]: Invalid JSON: " + value);
36
+ warn("Invalid JSON: " + value);
36
37
  return null;
37
38
  }
38
- case "boolean":
39
- return value; // conversion already handled above
40
39
  case "number":
41
40
  return value !== null ? +value : value;
42
41
  default:
@@ -54,7 +53,7 @@ export function getPropValue(type, value, transform) {
54
53
  */
55
54
  export function syncAttribute(element, name, value) {
56
55
  if (!element) {
57
- console.warn("░█ [ELENA]: Cannot sync attrs.");
56
+ warn("Cannot sync attrs.");
58
57
  return;
59
58
  }
60
59
  if (value === null) {
@@ -69,7 +68,7 @@ export function syncAttribute(element, name, value) {
69
68
  * at class-creation time. Values are stored per-instance
70
69
  * via a `_props` Map that is lazily created.
71
70
  *
72
- * @param {Function} proto - The class prototype
71
+ * @param {Object} proto - The class prototype
73
72
  * @param {string[]} propNames - Prop names to define
74
73
  * @param {Set<string>} [noReflect] - Props that should not reflect to attributes
75
74
  */
@@ -80,7 +79,7 @@ export function setProps(proto, propNames, noReflect) {
80
79
  configurable: true,
81
80
  enumerable: true,
82
81
  get() {
83
- return this._props ? this._props.get(prop) : undefined;
82
+ return this._props?.get(prop);
84
83
  },
85
84
  set(value) {
86
85
  if (!this._props) {
@@ -124,7 +123,7 @@ export function getProps(context, name, oldValue, newValue) {
124
123
  if (oldValue !== newValue) {
125
124
  const type = typeof context[name];
126
125
  if (type === "undefined") {
127
- console.warn(`░█ [ELENA]: Prop "${name}" has no default.`);
126
+ warn(`Prop "${name}" has no default.`);
128
127
  }
129
128
  const newAttr = getPropValue(type, newValue, "toProp");
130
129
  context[name] = newAttr;