@elenajs/core 1.0.0-rc.11 → 1.0.0-rc.13
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/dist/bundle.js +2 -2
- package/dist/common/props.d.ts +2 -2
- package/dist/common/props.d.ts.map +1 -1
- package/dist/common/utils.d.ts +1 -1
- package/dist/common/utils.d.ts.map +1 -1
- package/dist/elena.d.ts +4 -1
- package/dist/elena.d.ts.map +1 -1
- package/dist/elena.js +2 -2
- package/dist/utils.js +1 -1
- package/package.json +14 -2
- package/src/common/props.js +1 -1
- package/src/common/render.js +8 -8
- package/src/common/utils.js +4 -4
- package/src/elena.js +17 -8
package/dist/bundle.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @elenajs/core v1.0.0-rc.
|
|
2
|
+
* @elenajs/core v1.0.0-rc.13
|
|
3
3
|
* (c) 2025-present Ariel Salminen and Elena contributors
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
|
-
const t="░█ [ELENA]: ",s=Array.isArray,i=Symbol("elena.raw"),n=s=>console.warn(t+s),e={"&":"&","<":"<",">":">",'"':""","'":"'"};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])
|
|
6
|
+
const t="░█ [ELENA]: ",s=Array.isArray,i=Symbol("elena.raw"),n=s=>console.warn(t+s),e={"&":"&","<":"<",">":">",'"':""","'":"'"};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};
|
package/dist/common/props.d.ts
CHANGED
|
@@ -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 {
|
|
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:
|
|
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":"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,
|
|
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"}
|
package/dist/common/utils.d.ts
CHANGED
|
@@ -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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/common/utils.js"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,uCAHW,MAAM,
|
|
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
|
@@ -21,13 +21,15 @@ export type ElenaInstanceMembers = {
|
|
|
21
21
|
requestUpdate(): void;
|
|
22
22
|
connectedCallback(): void;
|
|
23
23
|
disconnectedCallback(): void;
|
|
24
|
+
adoptedCallback(): void;
|
|
25
|
+
attributeChangedCallback(prop: string, oldValue: string | null, newValue: string | null): void;
|
|
24
26
|
};
|
|
25
27
|
export type ElenaPropObject = {
|
|
26
28
|
name: string;
|
|
27
29
|
reflect?: boolean;
|
|
28
30
|
};
|
|
29
31
|
export type ElenaElementConstructor = (new (...args: any[]) => HTMLElement & ElenaInstanceMembers) & {
|
|
30
|
-
define(): void;
|
|
32
|
+
define(registry?: CustomElementRegistry): void;
|
|
31
33
|
readonly observedAttributes: string[];
|
|
32
34
|
tagName?: string;
|
|
33
35
|
props?: (string | ElenaPropObject)[];
|
|
@@ -35,6 +37,7 @@ export type ElenaElementConstructor = (new (...args: any[]) => HTMLElement & Ele
|
|
|
35
37
|
element?: string;
|
|
36
38
|
shadow?: "open" | "closed";
|
|
37
39
|
styles?: CSSStyleSheet | string | (CSSStyleSheet | string)[];
|
|
40
|
+
registry?: CustomElementRegistry;
|
|
38
41
|
};
|
|
39
42
|
import { html } from "./common/utils.js";
|
|
40
43
|
import { unsafeHTML } from "./common/utils.js";
|
package/dist/elena.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elena.d.ts","sourceRoot":"","sources":["../src/elena.js"],"names":[],"mappings":"
|
|
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.
|
|
2
|
+
* @elenajs/core v1.0.0-rc.13
|
|
3
3
|
* (c) 2025-present Ariel Salminen and Elena contributors
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
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;this._shadow
|
|
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/utils.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const t="░█ [ELENA]: ",n=Array.isArray,r=Symbol("elena.raw"),s=n=>console.warn(t+n);function e(t,n){const r
|
|
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={"&":"&","<":"<",">":">",'"':""","'":"'"};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.
|
|
3
|
+
"version": "1.0.0-rc.13",
|
|
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",
|
|
@@ -56,5 +68,5 @@
|
|
|
56
68
|
"typescript": "6.0.2",
|
|
57
69
|
"vitest": "4.1.1"
|
|
58
70
|
},
|
|
59
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "4e5ce73b7e4b80194e31e84d5eb6cf4c8d0a5f5f"
|
|
60
72
|
}
|
package/src/common/props.js
CHANGED
|
@@ -68,7 +68,7 @@ export function syncAttribute(element, name, value) {
|
|
|
68
68
|
* at class-creation time. Values are stored per-instance
|
|
69
69
|
* via a `_props` Map that is lazily created.
|
|
70
70
|
*
|
|
71
|
-
* @param {
|
|
71
|
+
* @param {Object} proto - The class prototype
|
|
72
72
|
* @param {string[]} propNames - Prop names to define
|
|
73
73
|
* @param {Set<string>} [noReflect] - Props that should not reflect to attributes
|
|
74
74
|
*/
|
package/src/common/render.js
CHANGED
|
@@ -20,10 +20,10 @@ const treeWalker = node => document.createTreeWalker(node, SHOW_COMMENT);
|
|
|
20
20
|
* @returns {boolean}
|
|
21
21
|
*/
|
|
22
22
|
export function renderTemplate(element, strings, values) {
|
|
23
|
-
if (
|
|
23
|
+
if (patch(element, strings, values)) {
|
|
24
24
|
return false;
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
morph(element, strings, values);
|
|
27
27
|
return true;
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -33,9 +33,9 @@ export function renderTemplate(element, strings, values) {
|
|
|
33
33
|
* @param {HTMLElement} element - The host element with cached template state
|
|
34
34
|
* @param {TemplateStringsArray} strings - Static parts of the tagged template
|
|
35
35
|
* @param {Array} values - Dynamic interpolated values
|
|
36
|
-
* @returns {boolean} Whether patching was sufficient (false =
|
|
36
|
+
* @returns {boolean} Whether patching was sufficient (false = do morph instead)
|
|
37
37
|
*/
|
|
38
|
-
function
|
|
38
|
+
function patch(element, strings, values) {
|
|
39
39
|
// Only works when re-rendering the same template shape
|
|
40
40
|
if (element._templateStrings !== strings || !element._templateParts) {
|
|
41
41
|
return false;
|
|
@@ -76,13 +76,13 @@ function patchParts(element, strings, values) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
|
-
* Clone a cached <template> and
|
|
79
|
+
* Clone a cached <template> and morph in new structure.
|
|
80
80
|
*
|
|
81
81
|
* @param {HTMLElement} element - The host element to render into
|
|
82
82
|
* @param {TemplateStringsArray} strings - Static parts of the tagged template
|
|
83
83
|
* @param {Array} values - Dynamic interpolated values
|
|
84
84
|
*/
|
|
85
|
-
function
|
|
85
|
+
function morph(element, strings, values) {
|
|
86
86
|
let entry = stringsCache.get(strings);
|
|
87
87
|
|
|
88
88
|
if (!entry) {
|
|
@@ -117,7 +117,7 @@ function fullRender(element, strings, values) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
|
-
*
|
|
120
|
+
* Create a <template> element with comment markers and string placeholders.
|
|
121
121
|
*
|
|
122
122
|
* @param {string[]} _strings - Whitespace-collapsed static parts
|
|
123
123
|
* @param {number} valueCount - Number of dynamic values
|
|
@@ -172,7 +172,7 @@ function createTemplate(_strings, valueCount) {
|
|
|
172
172
|
* @param {HTMLElement} element - The host element to render into
|
|
173
173
|
* @param {{ _tpl: HTMLTemplateElement, _attrs: (string|null)[] }} templateInfo
|
|
174
174
|
* @param {Array} values - Raw interpolated values
|
|
175
|
-
* @returns {Array<Text | [Element, string] | undefined>}
|
|
175
|
+
* @returns {Array<Text | [Element, string] | undefined> | null}
|
|
176
176
|
*/
|
|
177
177
|
function cloneAndPatch(element, templateInfo, values) {
|
|
178
178
|
const { _tpl, _attrs } = templateInfo;
|
package/src/common/utils.js
CHANGED
|
@@ -15,9 +15,9 @@ export { prefix, isArray };
|
|
|
15
15
|
* @param {string} tagName
|
|
16
16
|
* @param {Function} Element
|
|
17
17
|
*/
|
|
18
|
-
export function defineElement(tagName, Element) {
|
|
19
|
-
const
|
|
20
|
-
|
|
18
|
+
export function defineElement(tagName, Element, registry) {
|
|
19
|
+
const reg = registry ?? globalThis.customElements;
|
|
20
|
+
reg?.get(tagName) || reg?.define(tagName, Element);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -113,7 +113,7 @@ export const nothing = { [RAW]: true, toString: () => "" };
|
|
|
113
113
|
* @param {*} value
|
|
114
114
|
* @returns {boolean}
|
|
115
115
|
*/
|
|
116
|
-
export const isRaw = value => (isArray(value) ? value.some(item => item?.[RAW]) : value?.[RAW]);
|
|
116
|
+
export const isRaw = value => (isArray(value) ? value.some(item => item?.[RAW]) : !!value?.[RAW]);
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
119
|
* Convert a value to its plain text string.
|
package/src/elena.js
CHANGED
|
@@ -40,7 +40,7 @@ function elementResolver(selector) {
|
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* @typedef {{ text: string, element: HTMLElement | null, updateComplete: Promise<void>, render(): void, willUpdate(): void, firstUpdated(): void, updated(): void, requestUpdate(): void, connectedCallback(): void, disconnectedCallback(): void }} ElenaInstanceMembers
|
|
43
|
+
* @typedef {{ text: string, element: HTMLElement | null, updateComplete: Promise<void>, render(): void, willUpdate(): void, firstUpdated(): void, updated(): void, requestUpdate(): void, connectedCallback(): void, disconnectedCallback(): void, adoptedCallback(): void, attributeChangedCallback(prop: string, oldValue: string | null, newValue: string | null): void }} ElenaInstanceMembers
|
|
44
44
|
*/
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -49,7 +49,7 @@ function elementResolver(selector) {
|
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* @typedef {(new (...args: any[]) => HTMLElement & ElenaInstanceMembers) & {
|
|
52
|
-
* define(): void,
|
|
52
|
+
* define(registry?: CustomElementRegistry): void,
|
|
53
53
|
* readonly observedAttributes: string[],
|
|
54
54
|
* tagName?: string,
|
|
55
55
|
* props?: (string | ElenaPropObject)[],
|
|
@@ -57,6 +57,7 @@ function elementResolver(selector) {
|
|
|
57
57
|
* element?: string,
|
|
58
58
|
* shadow?: "open" | "closed",
|
|
59
59
|
* styles?: CSSStyleSheet | string | (CSSStyleSheet | string)[],
|
|
60
|
+
* registry?: CustomElementRegistry,
|
|
60
61
|
* }} ElenaElementConstructor
|
|
61
62
|
*/
|
|
62
63
|
|
|
@@ -91,8 +92,8 @@ export function Elena(superClass) {
|
|
|
91
92
|
* Updates the matching prop and re-renders if needed.
|
|
92
93
|
*
|
|
93
94
|
* @param {string} prop
|
|
94
|
-
* @param {string} oldValue
|
|
95
|
-
* @param {string} newValue
|
|
95
|
+
* @param {string | null} oldValue
|
|
96
|
+
* @param {string | null} newValue
|
|
96
97
|
*/
|
|
97
98
|
attributeChangedCallback(prop, oldValue, newValue) {
|
|
98
99
|
super.attributeChangedCallback?.(prop, oldValue, newValue);
|
|
@@ -267,7 +268,11 @@ export function Elena(superClass) {
|
|
|
267
268
|
// In that case skip attachShadow() but still adopt styles below.
|
|
268
269
|
// Store the reference so closed shadow roots remain accessible.
|
|
269
270
|
if (!this._shadow && !this.shadowRoot) {
|
|
270
|
-
|
|
271
|
+
const options = { mode: component.shadow };
|
|
272
|
+
if (component.registry) {
|
|
273
|
+
options.customElementRegistry = component.registry;
|
|
274
|
+
}
|
|
275
|
+
this._shadow = this.attachShadow(options);
|
|
271
276
|
}
|
|
272
277
|
|
|
273
278
|
const shadowRoot = this._shadow ?? this.shadowRoot;
|
|
@@ -309,7 +314,7 @@ export function Elena(superClass) {
|
|
|
309
314
|
const rebuilt = renderTemplate(root, result.strings, result.values);
|
|
310
315
|
|
|
311
316
|
// Re-resolve element ref when the DOM was fully rebuilt.
|
|
312
|
-
//
|
|
317
|
+
// patch() and morph() leave the DOM structure intact,
|
|
313
318
|
// so the existing ref is still valid.
|
|
314
319
|
if (rebuilt) {
|
|
315
320
|
const oldElement = this.element;
|
|
@@ -442,6 +447,7 @@ export function Elena(superClass) {
|
|
|
442
447
|
* events in Shadow DOM (change, submit, reset).
|
|
443
448
|
* Composed bubbling events (click, input) pass through on their own.
|
|
444
449
|
*
|
|
450
|
+
* @param {Event} event
|
|
445
451
|
* @internal
|
|
446
452
|
*/
|
|
447
453
|
handleEvent(event) {
|
|
@@ -479,11 +485,14 @@ export function Elena(superClass) {
|
|
|
479
485
|
* Registers the component as a custom element using `static tagName`.
|
|
480
486
|
* Call this on your component class after the class body is defined,
|
|
481
487
|
* not on the Elena mixin itself.
|
|
488
|
+
*
|
|
489
|
+
* @param {CustomElementRegistry} [registry] - A scoped registry to register in.
|
|
490
|
+
* When omitted, registers in the global `customElements` registry.
|
|
482
491
|
*/
|
|
483
|
-
static define() {
|
|
492
|
+
static define(registry) {
|
|
484
493
|
const tag = this.tagName;
|
|
485
494
|
if (tag) {
|
|
486
|
-
defineElement(tag, this);
|
|
495
|
+
defineElement(tag, this, registry);
|
|
487
496
|
} else {
|
|
488
497
|
warn("define() without a tagName.");
|
|
489
498
|
}
|