diff --git a/dist/dde-with-observables.js b/dist/dde-with-observables.js index fab17cf..3907924 100644 --- a/dist/dde-with-observables.js +++ b/dist/dde-with-observables.js @@ -1,6 +1,6 @@ //deka-dom-el library is available via global namespace `dde` (()=> { -var A={isObservable(e){return!1},processReactiveAttribute(e,t,n,r){return n}};function T(e,t=!0){return t?Object.assign(A,e):(Object.setPrototypeOf(e,A),e)}function C(e){return A.isPrototypeOf(e)&&e!==A?e:A}function x(e){return typeof e>"u"}function B(e){let t=typeof e;return t!=="object"?t:e===null?"null":Object.prototype.toString.call(e)}function N(e,t){if(!e||!(e instanceof AbortSignal))return!0;if(!e.aborted)return e.addEventListener("abort",t),function(){e.removeEventListener("abort",t)}}var $={setDeleteAttr:ee,ssr:""};function ee(e,t,n){if(Reflect.set(e,t,n),!!x(n)){if(Reflect.deleteProperty(e,t),e instanceof HTMLElement&&e.getAttribute(t)==="undefined")return e.removeAttribute(t);if(Reflect.get(e,t)==="undefined")return Reflect.set(e,t,"")}}var E=[{scope:document.body,host:e=>e?e(document.body):document.body,custom_element:!1,prevent:!0}],b={get current(){return E[E.length-1]},get host(){return this.current.host},preventDefault(){let{current:e}=this;return e.prevent=!0,e},get state(){return[...E]},push(e={}){return E.push(Object.assign({},this.current,{prevent:!1},e))},pushRoot(){return E.push(E[0])},pop(){if(E.length!==1)return E.pop()}};function H(...e){return this.appendOriginal(...e),this}function te(e){return e.append===H||(e.appendOriginal=e.append,e.append=H),e}var j;function y(e,t,...n){let r=C(this),o=0,c,s;switch((Object(t)!==t||r.isObservable(t))&&(t={textContent:t}),!0){case typeof e=="function":{o=1,b.push({scope:e,host:(...l)=>l.length?(o===1?n.unshift(...l):l.forEach(v=>v(s)),void 0):s}),c=e(t||void 0);let d=c instanceof DocumentFragment;if(c.nodeName==="#comment")break;let u=y.mark({type:"component",name:e.name,host:d?"this":"parentElement"});c.prepend(u),d&&(s=u);break}case e==="#text":c=P.call(this,document.createTextNode(""),t);break;case(e==="<>"||!e):c=P.call(this,document.createDocumentFragment(),t);break;case!!j:c=P.call(this,document.createElementNS(j,e),t);break;case!c:c=P.call(this,document.createElement(e),t)}return te(c),s||(s=c),n.forEach(d=>d(s)),o&&b.pop(),o=2,c}function _e(e){let t=Symbol.for("default"),n=Array.from(e.querySelectorAll("slot")).reduce((o,c)=>Reflect.set(o,c.name||t,c)&&o,{}),r=Reflect.has(n,t);return e.append=new Proxy(e.append,{apply(o,c,s){if(!s.length)return e;let d=document.createDocumentFragment();for(let u of s){if(!u||!u.slot){r&&d.appendChild(u);continue}let l=u.slot,v=n[l];O(u,"remove","slot"),v&&(v.replaceWith(u),Reflect.deleteProperty(n,l))}return r&&(n[t].replaceWith(d),Reflect.deleteProperty(n,t)),Object.values(n).forEach(u=>u.replaceWith(y().append(...Array.from(u.childNodes)))),e}}),e}y.mark=function(e,t=!1){e=Object.entries(e).map(([o,c])=>o+`="${c}"`).join(" ");let n=t?"":"/",r=document.createComment(``);return t||(r.end=document.createComment("")),r};function Ee(e){let t=this;return function(...r){j=e;let o=y.call(t,...r);return j=void 0,o}}var{setDeleteAttr:I}=$,L=new WeakMap;function P(e,...t){if(!t.length)return e;L.set(e,G(e,this));for(let[n,r]of Object.entries(Object.assign({},...t)))Z.call(this,e,n,r);return L.delete(e),e}function Z(e,t,n){let{setRemoveAttr:r,s:o}=G(e,this),c=this;n=o.processReactiveAttribute(e,t,n,(d,u)=>Z.call(c,e,d,u));let[s]=t;if(s==="=")return r(t.slice(1),n);if(s===".")return J(e,t.slice(1),n);if(/(aria|data)([A-Z])/.test(t))return t=t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),r(t,n);switch(t==="className"&&(t="class"),t){case"xlink:href":return r(t,n,"http://www.w3.org/1999/xlink");case"textContent":return I(e,t,n);case"style":if(typeof n!="object")break;case"dataset":return F(o,n,J.bind(null,e[t]));case"ariaset":return F(o,n,(d,u)=>r("aria-"+d,u));case"classList":return ne.call(c,e,n)}return re(e,t)?I(e,t,n):r(t,n)}function G(e,t){if(L.has(e))return L.get(e);let r=(e instanceof SVGElement?ce:oe).bind(null,e,"Attribute"),o=C(t);return{setRemoveAttr:r,s:o}}function ne(e,t){let n=C(this);return F(n,t,(r,o)=>e.classList.toggle(r,o===-1?void 0:!!o)),e}function xe(e){return Array.from(e.children).forEach(t=>t.remove()),e}function O(e,t,n,r){return e instanceof HTMLElement?e[t+"Attribute"](n,r):e[t+"AttributeNS"](null,n,r)}function re(e,t){if(!Reflect.has(e,t))return!1;let n=V(e,t);return!x(n.set)}function V(e,t){if(e=Object.getPrototypeOf(e),!e)return{};let n=Object.getOwnPropertyDescriptor(e,t);return n||V(e,t)}function F(e,t,n){if(!(typeof t!="object"||t===null))return Object.entries(t).forEach(function([o,c]){o&&(c=e.processReactiveAttribute(t,o,c,n),n(o,c))})}function K(e){return Array.isArray(e)?e.filter(Boolean).join(" "):e}function oe(e,t,n,r){return e[(x(r)?"remove":"set")+t](n,K(r))}function ce(e,t,n,r,o=null){return e[(x(r)?"remove":"set")+t+"NS"](o,n,K(r))}function J(e,t,n){if(Reflect.set(e,t,n),!!x(n))return Reflect.deleteProperty(e,t)}function we(e,t,n){return t||(t={}),function(o,...c){n&&(c.unshift(o),o=typeof n=="function"?n():n);let s=c.length?new CustomEvent(e,Object.assign({detail:c[0]},t)):new Event(e,t);return o.dispatchEvent(s)}}function _(e,t,n){return function(o){return o.addEventListener(e,t,n),o}}var D=ie(),se=new WeakSet;_.connected=function(e,t){let{custom_element:n}=b.current,r="connected";return typeof t!="object"&&(t={}),t.once=!0,function(c){n&&(c=n);let s="dde:"+r;return c.addEventListener(s,e,t),c.__dde_lifecycleToEvents?c:c.isConnected?(c.dispatchEvent(new Event(s)),c):(N(t.signal,()=>D.offConnected(c,e))&&D.onConnected(c,e),c)}};_.disconnected=function(e,t){let{custom_element:n}=b.current,r="disconnected";return typeof t!="object"&&(t={}),t.once=!0,function(c){n&&(c=n);let s="dde:"+r;return c.addEventListener(s,e,t),c.__dde_lifecycleToEvents||N(t.signal,()=>D.offDisconnected(c,e))&&D.onDisconnected(c,e),c}};var z=new WeakMap;_.disconnectedAsAbort=function(e){if(z.has(e))return z.get(e);let t=new AbortController;return z.set(e,t),e(_.disconnected(()=>t.abort())),t};_.attributeChanged=function(e,t){let n="attributeChanged";return typeof t!="object"&&(t={}),function(o){let c="dde:"+n;if(o.addEventListener(c,e,t),o.__dde_lifecycleToEvents||se.has(o))return o;let s=new MutationObserver(function(u){for(let{attributeName:l,target:v}of u)v.dispatchEvent(new CustomEvent(c,{detail:[l,v.getAttribute(l)]}))});return N(t.signal,()=>s.disconnect())&&s.observe(o,{attributes:!0}),o}};function ie(){let e=new Map,t=!1,n=new MutationObserver(function(i){for(let f of i)if(f.type==="childList"){if(l(f.addedNodes,!0)){s();continue}v(f.removedNodes,!0)&&s()}});return{onConnected(i,f){c();let a=o(i);a.connected.has(f)||(a.connected.add(f),a.length_c+=1)},offConnected(i,f){if(!e.has(i))return;let a=e.get(i);a.connected.has(f)&&(a.connected.delete(f),a.length_c-=1,r(i,a))},onDisconnected(i,f){c();let a=o(i);a.disconnected.has(f)||(a.disconnected.add(f),a.length_d+=1)},offDisconnected(i,f){if(!e.has(i))return;let a=e.get(i);a.disconnected.has(f)&&(a.disconnected.delete(f),a.length_d-=1,r(i,a))}};function r(i,f){f.length_c||f.length_d||(e.delete(i),s())}function o(i){if(e.has(i))return e.get(i);let f={connected:new WeakSet,length_c:0,disconnected:new WeakSet,length_d:0};return e.set(i,f),f}function c(){t||(t=!0,n.observe(document.body,{childList:!0,subtree:!0}))}function s(){!t||e.size||(t=!1,n.disconnect())}function d(){return new Promise(function(i){(requestIdleCallback||requestAnimationFrame)(i)})}async function u(i){e.size>30&&await d();let f=[];if(!(i instanceof Node))return f;for(let a of e.keys())a===i||!(a instanceof Node)||i.contains(a)&&f.push(a);return f}function l(i,f){let a=!1;for(let g of i){if(f&&u(g).then(l),!e.has(g))continue;let w=e.get(g);w.length_c&&(g.dispatchEvent(new Event("dde:connected")),w.connected=new WeakSet,w.length_c=0,w.length_d||e.delete(g),a=!0)}return a}function v(i,f){let a=!1;for(let g of i)f&&u(g).then(v),!(!e.has(g)||!e.get(g).length_d)&&(g.dispatchEvent(new Event("dde:disconnected")),e.delete(g),a=!0);return a}}var p=Symbol.for("observable");function W(e){try{return Reflect.has(e,p)}catch{return!1}}var M=[],h=new WeakMap;function m(e,t){if(typeof e!="function")return Q(e,t);if(W(e))return e;let n=Q(),r=function(){let[o,...c]=h.get(r);if(h.set(r,new Set([o])),M.push(r),n(e()),M.pop(),!c.length)return;let s=h.get(r);for(let d of c)s.has(d)||S(d,r)};return h.set(n[p],r),h.set(r,new Set([n])),r(),n}m.action=function(e,t,...n){let r=e[p],{actions:o}=r;if(!o||!Reflect.has(o,t))throw new Error(`'${e}' has no action with name '${t}'!`);if(o[t].apply(r,n),r.skip)return Reflect.deleteProperty(r,"skip");r.listeners.forEach(c=>c(r.value))};m.on=function e(t,n,r={}){let{signal:o}=r;if(!(o&&o.aborted)){if(Array.isArray(t))return t.forEach(c=>e(c,n,r));U(t,n),o&&o.addEventListener("abort",()=>S(t,n))}};m.symbols={observable:p,onclear:Symbol.for("Observable.onclear")};m.clear=function(...e){for(let n of e){Reflect.deleteProperty(n,"toJSON");let r=n[p];r.onclear.forEach(o=>o.call(r)),t(n,r),Reflect.deleteProperty(n,p)}function t(n,r){r.listeners.forEach(o=>{if(r.listeners.delete(o),!h.has(o))return;let c=h.get(o);c.delete(n),!(c.size>1)&&(n.clear(...c),h.delete(o))})}};var k="__dde_reactive";m.el=function(e,t){let n=y.mark({type:"reactive"},!1),r=n.end,o=document.createDocumentFragment();o.append(n,r);let{current:c}=b,s=d=>{if(!n.parentNode||!r.parentNode)return S(e,s);b.push(c);let u=t(d);b.pop(),Array.isArray(u)||(u=[u]);let l=n;for(;(l=n.nextSibling)!==r;)l.remove();n.after(...u)};return U(e,s),Y(e,s,n,t),s(e()),o};var R="__dde_attributes";m.attribute=function(e,t=null){let n=m(t),r;return b.host(o=>{if(r=o,O(r,"has",e)?n(O(r,"get",e)):t!==null&&O(r,"set",e,t),o[R]){o[R][e]=n;return}r[R]={[e]:n},_.attributeChanged(function({detail:s}){/*! This maps attributes to observables (`S.attribute`). +var A={isObservable(e){return!1},processReactiveAttribute(e,t,n,r){return n}};function T(e,t=!0){return t?Object.assign(A,e):(Object.setPrototypeOf(e,A),e)}function C(e){return A.isPrototypeOf(e)&&e!==A?e:A}function x(e){return typeof e>"u"}function B(e){let t=typeof e;return t!=="object"?t:e===null?"null":Object.prototype.toString.call(e)}function N(e,t){if(!e||!(e instanceof AbortSignal))return!0;if(!e.aborted)return e.addEventListener("abort",t),function(){e.removeEventListener("abort",t)}}var $={setDeleteAttr:ee,ssr:""};function ee(e,t,n){if(Reflect.set(e,t,n),!!x(n)){if(Reflect.deleteProperty(e,t),e instanceof HTMLElement&&e.getAttribute(t)==="undefined")return e.removeAttribute(t);if(Reflect.get(e,t)==="undefined")return Reflect.set(e,t,"")}}var E=[{scope:document.body,host:e=>e?e(document.body):document.body,custom_element:!1,prevent:!0}],b={get current(){return E[E.length-1]},get host(){return this.current.host},preventDefault(){let{current:e}=this;return e.prevent=!0,e},get state(){return[...E]},push(e={}){return E.push(Object.assign({},this.current,{prevent:!1},e))},pushRoot(){return E.push(E[0])},pop(){if(E.length!==1)return E.pop()}};function H(...e){return this.appendOriginal(...e),this}function te(e){return e.append===H||(e.appendOriginal=e.append,e.append=H),e}var j;function y(e,t,...n){let r=C(this),o=0,c,s;switch((Object(t)!==t||r.isObservable(t))&&(t={textContent:t}),!0){case typeof e=="function":{o=1,b.push({scope:e,host:(...l)=>l.length?(o===1?n.unshift(...l):l.forEach(v=>v(s)),void 0):s}),c=e(t||void 0);let d=c instanceof DocumentFragment;if(c.nodeName==="#comment")break;let u=y.mark({type:"component",name:e.name,host:d?"this":"parentElement"});c.prepend(u),d&&(s=u);break}case e==="#text":c=P.call(this,document.createTextNode(""),t);break;case(e==="<>"||!e):c=P.call(this,document.createDocumentFragment(),t);break;case!!j:c=P.call(this,document.createElementNS(j,e),t);break;case!c:c=P.call(this,document.createElement(e),t)}return te(c),s||(s=c),n.forEach(d=>d(s)),o&&b.pop(),o=2,c}function _e(e){let t=Symbol.for("default"),n=Array.from(e.querySelectorAll("slot")).reduce((o,c)=>Reflect.set(o,c.name||t,c)&&o,{}),r=Reflect.has(n,t);return e.append=new Proxy(e.append,{apply(o,c,s){if(!s.length)return e;let d=document.createDocumentFragment();for(let u of s){if(!u||!u.slot){r&&d.appendChild(u);continue}let l=u.slot,v=n[l];O(u,"remove","slot"),v&&(v.replaceWith(u),Reflect.deleteProperty(n,l))}return r&&(n[t].replaceWith(d),Reflect.deleteProperty(n,t)),Object.values(n).forEach(u=>u.replaceWith(y().append(...Array.from(u.childNodes)))),e}}),e}y.mark=function(e,t=!1){e=Object.entries(e).map(([o,c])=>o+`="${c}"`).join(" ");let n=t?"":"/",r=document.createComment(``);return t||(r.end=document.createComment("")),r};function Ee(e){let t=this;return function(...r){j=e;let o=y.call(t,...r);return j=void 0,o}}var{setDeleteAttr:I}=$,L=new WeakMap;function P(e,...t){if(!t.length)return e;L.set(e,G(e,this));for(let[n,r]of Object.entries(Object.assign({},...t)))Z.call(this,e,n,r);return L.delete(e),e}function Z(e,t,n){let{setRemoveAttr:r,s:o}=G(e,this),c=this;n=o.processReactiveAttribute(e,t,n,(d,u)=>Z.call(c,e,d,u));let[s]=t;if(s==="=")return r(t.slice(1),n);if(s===".")return J(e,t.slice(1),n);if(/(aria|data)([A-Z])/.test(t))return t=t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),r(t,n);switch(t==="className"&&(t="class"),t){case"xlink:href":return r(t,n,"http://www.w3.org/1999/xlink");case"textContent":return I(e,t,n);case"style":if(typeof n!="object")break;case"dataset":return F(o,n,J.bind(null,e[t]));case"ariaset":return F(o,n,(d,u)=>r("aria-"+d,u));case"classList":return ne.call(c,e,n)}return re(e,t)?I(e,t,n):r(t,n)}function G(e,t){if(L.has(e))return L.get(e);let r=(e instanceof SVGElement?ce:oe).bind(null,e,"Attribute"),o=C(t);return{setRemoveAttr:r,s:o}}function ne(e,t){let n=C(this);return F(n,t,(r,o)=>e.classList.toggle(r,o===-1?void 0:!!o)),e}function xe(e){return Array.from(e.children).forEach(t=>t.remove()),e}function O(e,t,n,r){return e instanceof HTMLElement?e[t+"Attribute"](n,r):e[t+"AttributeNS"](null,n,r)}function re(e,t){if(!Reflect.has(e,t))return!1;let n=V(e,t);return!x(n.set)}function V(e,t){if(e=Object.getPrototypeOf(e),!e)return{};let n=Object.getOwnPropertyDescriptor(e,t);return n||V(e,t)}function F(e,t,n){if(!(typeof t!="object"||t===null))return Object.entries(t).forEach(function([o,c]){o&&(c=e.processReactiveAttribute(t,o,c,n),n(o,c))})}function K(e){return Array.isArray(e)?e.filter(Boolean).join(" "):e}function oe(e,t,n,r){return e[(x(r)?"remove":"set")+t](n,K(r))}function ce(e,t,n,r,o=null){return e[(x(r)?"remove":"set")+t+"NS"](o,n,K(r))}function J(e,t,n){if(Reflect.set(e,t,n),!!x(n))return Reflect.deleteProperty(e,t)}function we(e,t,n){return t||(t={}),function(o,...c){n&&(c.unshift(o),o=typeof n=="function"?n():n);let s=c.length?new CustomEvent(e,Object.assign({detail:c[0]},t)):new Event(e,t);return o.dispatchEvent(s)}}function _(e,t,n){return function(o){return o.addEventListener(e,t,n),o}}var D=ie(),se=new WeakSet;_.connected=function(e,t){let{custom_element:n}=b.current,r="connected";return typeof t!="object"&&(t={}),t.once=!0,function(c){n&&(c=n);let s="dde:"+r;return c.addEventListener(s,e,t),c.__dde_lifecycleToEvents?c:c.isConnected?(c.dispatchEvent(new Event(s)),c):(N(t.signal,()=>D.offConnected(c,e))&&D.onConnected(c,e),c)}};_.disconnected=function(e,t){let{custom_element:n}=b.current,r="disconnected";return typeof t!="object"&&(t={}),t.once=!0,function(c){n&&(c=n);let s="dde:"+r;return c.addEventListener(s,e,t),c.__dde_lifecycleToEvents||N(t.signal,()=>D.offDisconnected(c,e))&&D.onDisconnected(c,e),c}};var z=new WeakMap;_.disconnectedAsAbort=function(e){if(z.has(e))return z.get(e);let t=new AbortController;return z.set(e,t),e(_.disconnected(()=>t.abort())),t};_.attributeChanged=function(e,t){let n="attributeChanged";return typeof t!="object"&&(t={}),function(o){let c="dde:"+n;if(o.addEventListener(c,e,t),o.__dde_lifecycleToEvents||se.has(o))return o;let s=new MutationObserver(function(u){for(let{attributeName:l,target:v}of u)v.dispatchEvent(new CustomEvent(c,{detail:[l,v.getAttribute(l)]}))});return N(t.signal,()=>s.disconnect())&&s.observe(o,{attributes:!0}),o}};function ie(){let e=new Map,t=!1,n=new MutationObserver(function(i){for(let f of i)if(f.type==="childList"){if(l(f.addedNodes,!0)){s();continue}v(f.removedNodes,!0)&&s()}});return{onConnected(i,f){c();let a=o(i);a.connected.has(f)||(a.connected.add(f),a.length_c+=1)},offConnected(i,f){if(!e.has(i))return;let a=e.get(i);a.connected.has(f)&&(a.connected.delete(f),a.length_c-=1,r(i,a))},onDisconnected(i,f){c();let a=o(i);a.disconnected.has(f)||(a.disconnected.add(f),a.length_d+=1)},offDisconnected(i,f){if(!e.has(i))return;let a=e.get(i);a.disconnected.has(f)&&(a.disconnected.delete(f),a.length_d-=1,r(i,a))}};function r(i,f){f.length_c||f.length_d||(e.delete(i),s())}function o(i){if(e.has(i))return e.get(i);let f={connected:new WeakSet,length_c:0,disconnected:new WeakSet,length_d:0};return e.set(i,f),f}function c(){t||(t=!0,n.observe(document.body,{childList:!0,subtree:!0}))}function s(){!t||e.size||(t=!1,n.disconnect())}function d(){return new Promise(function(i){(requestIdleCallback||requestAnimationFrame)(i)})}async function u(i){e.size>30&&await d();let f=[];if(!(i instanceof Node))return f;for(let a of e.keys())a===i||!(a instanceof Node)||i.contains(a)&&f.push(a);return f}function l(i,f){let a=!1;for(let g of i){if(f&&u(g).then(l),!e.has(g))continue;let w=e.get(g);w.length_c&&(g.dispatchEvent(new Event("dde:connected")),w.connected=new WeakSet,w.length_c=0,w.length_d||e.delete(g),a=!0)}return a}function v(i,f){let a=!1;for(let g of i)f&&u(g).then(v),!(!e.has(g)||!e.get(g).length_d)&&(g.dispatchEvent(new Event("dde:disconnected")),e.delete(g),a=!0);return a}}var p=Symbol.for("observable");function W(e){try{return Reflect.has(e,p)}catch{return!1}}var M=[],h=new WeakMap;function m(e,t){if(typeof e!="function")return Q(e,t);if(W(e))return e;let n=Q(),r=function(){let[o,...c]=h.get(r);if(h.set(r,new Set([o])),M.push(r),n(e()),M.pop(),!c.length)return;let s=h.get(r);for(let d of c)s.has(d)||S(d,r)};return h.set(n[p],r),h.set(r,new Set([n])),r(),n}m.action=function(e,t,...n){let r=e[p],{actions:o}=r;if(!o||!Reflect.has(o,t))throw new Error(`'${e}' has no action with name '${t}'!`);if(o[t].apply(r,n),r.skip)return Reflect.deleteProperty(r,"skip");r.listeners.forEach(c=>c(r.value))};m.on=function e(t,n,r={}){let{signal:o}=r;if(!(o&&o.aborted)){if(Array.isArray(t))return t.forEach(c=>e(c,n,r));U(t,n),o&&o.addEventListener("abort",()=>S(t,n))}};m.symbols={onclear:Symbol.for("Observable.onclear")};m.clear=function(...e){for(let n of e){Reflect.deleteProperty(n,"toJSON");let r=n[p];r.onclear.forEach(o=>o.call(r)),t(n,r),Reflect.deleteProperty(n,p)}function t(n,r){r.listeners.forEach(o=>{if(r.listeners.delete(o),!h.has(o))return;let c=h.get(o);c.delete(n),!(c.size>1)&&(n.clear(...c),h.delete(o))})}};var k="__dde_reactive";m.el=function(e,t){let n=y.mark({type:"reactive"},!1),r=n.end,o=document.createDocumentFragment();o.append(n,r);let{current:c}=b,s=d=>{if(!n.parentNode||!r.parentNode)return S(e,s);b.push(c);let u=t(d);b.pop(),Array.isArray(u)||(u=[u]);let l=n;for(;(l=n.nextSibling)!==r;)l.remove();n.after(...u)};return U(e,s),Y(e,s,n,t),s(e()),o};var R="__dde_attributes";m.attribute=function(e,t=null){let n=m(t),r;return b.host(o=>{if(r=o,O(r,"has",e)?n(O(r,"get",e)):t!==null&&O(r,"set",e,t),o[R]){o[R][e]=n;return}r[R]={[e]:n},_.attributeChanged(function({detail:s}){/*! This maps attributes to observables (`S.attribute`). * Investigate `__dde_attributes` key of the element.*/let[d,u]=s,l=r[R][d];if(l)return l(u)})(r),_.disconnected(function(){/*! This removes all observables mapped to attributes (`S.attribute`). * Investigate `__dde_attributes` key of the element.*/m.clear(...Object.values(r[R]))})(r)}),new Proxy(n,{apply(o,c,s){if(!s.length)return o();let d=s[0];return O(r,"set",e,d)}})};var X={isObservable:W,processReactiveAttribute(e,t,n,r){if(!W(n))return n;let o=c=>r(t,c);return U(n,o),Y(n,o,e,t),n()}};function Y(e,t,...n){let{current:r}=b;r.prevent||r.host(function(o){o[k]||(o[k]=[],_.disconnected(()=>o[k].forEach(([[c,s]])=>S(c,s,c[p]?.host()===o)))(o)),o[k].push([[e,t],...n])})}function Q(e,t){let n=(...r)=>r.length?le(n,...r):de(n);return ue(n,e,t)}var fe=Object.assign(Object.create(null),{stopPropagation(){this.skip=!0}}),q=class extends Error{constructor(){super();let[t,...n]=this.stack.split(` `),r=t.slice(t.indexOf("@"),t.indexOf(".js:")+4);this.stack=n.find(o=>!o.includes(r))}};function ue(e,t,n){let r=[];B(n)!=="[object Object]"&&(n={});let{onclear:o}=m.symbols;n[o]&&(r.push(n[o]),Reflect.deleteProperty(n,o));let{host:c}=b;return Reflect.defineProperty(e,p,{value:{value:t,actions:n,onclear:r,host:c,listeners:new Set,defined:new q},enumerable:!1,writable:!1,configurable:!0}),e.toJSON=()=>e(),Object.setPrototypeOf(e[p],fe),e}function ae(){return M[M.length-1]}function de(e){if(!e[p])return;let{value:t,listeners:n}=e[p],r=ae();return r&&n.add(r),h.has(r)&&h.get(r).add(e),t}function le(e,t,n){if(!e[p])return;let r=e[p];if(!(!n&&r.value===t))return r.value=t,r.listeners.forEach(o=>o(t)),t}function U(e,t){if(e[p])return e[p].listeners.add(t)}function S(e,t,n){let r=e[p];if(!r)return;let o=r.listeners.delete(t);if(n&&!r.listeners.size){if(e.clear(e),!h.has(r))return o;let c=h.get(r);if(!h.has(c))return o;h.get(c).forEach(s=>S(s,c,!0))}return o}T(X); diff --git a/dist/esm-with-observables.d.ts b/dist/esm-with-observables.d.ts index 4c2f71d..f9cdf03 100644 --- a/dist/esm-with-observables.d.ts +++ b/dist/esm-with-observables.d.ts @@ -1,3 +1,68 @@ +export type Observable= (set?: V)=> V & A; +type Action= (this: { value: V, stopPropagation(): void }, ...a: any[])=> typeof observable._ | void; +//type SymbolObservable= Symbol; +type SymbolOnclear= symbol; +type Actions= Record>; +interface observable{ + _: Symbol + /** + * Simple example: + * ```js + * const hello= S("Hello Observable"); + * ``` + * …simple todo observable: + * ```js + * const todos= S([], { + * add(v){ this.value.push(S(v)); }, + * remove(i){ this.value.splice(i, 1); }, + * [S.symbols.onclear](){ S.clear(...this.value); }, + * }); + * ``` + * …computed observable: + * ```js + * const name= S("Jan"); + * const surname= S("Andrle"); + * const fullname= S(()=> name()+" "+surname()); + * ``` + * @param value Initial observable value. Or function computing value from other observables. + * @param actions Use to define actions on the observable. Such as add item to the array. + * There is also a reserved function `S.symbol.onclear` which is called when the observable is cleared + * by `S.clear`. + * */ + >(value: V, actions?: A): Observable; + /** + * Computations observable. This creates a observable which is computed from other observables. + * */ + (computation: ()=> V): Observable + action>, A extends (S extends Observable ? A : never), N extends keyof A>( + observable: S, + name: N, + ...params: A[N] extends (...args: infer P)=> any ? P : never + ): void; + clear(...observables: Observable[]): void; + on(observable: Observable, onchange: (a: T)=> void, options?: AddEventListenerOptions): void; + symbols: { + //observable: SymbolObservable; + onclear: SymbolOnclear; + } + /** + * Reactive element, which is rendered based on the given observable. + * ```js + * S.el(observable, value=> value ? el("b", "True") : el("i", "False")); + * S.el(listS, list=> list.map(li=> el("li", li))); + * ``` + * */ + el(observable: Observable, el: (v: S)=> Element | Element[] | DocumentFragment): DocumentFragment; + + attribute(name: string, initial?: string): Observable; +} +export const observable: observable; +export const O: observable; +declare global { + type ddeObservable= Observable; + type ddeAction= Action + type ddeActions= Actions +} type CustomElementTagNameMap= { '#text': Text, '#comment': Comment } declare global { interface ddePublicElementTagNameMap{ @@ -19,20 +84,21 @@ type AttrsModified= { /** * Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API). */ - style: string | Partial + style: string | Partial | Observable | Partial<{ [K in keyof CSSStyleDeclaration]: Observable }> /** * Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` for others. */ - classList: Record, + classList: Record>, /** * By default simiral to `className`, but also supports `string[]` * */ - className: string | (string|boolean|undefined)[]; + className: string | (string|boolean|undefined|Observable)[]; /** * Sets `aria-*` simiraly to `dataset` * */ - ariaset: Record, -} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, string> & Record<`.${string}`, any> + ariaset: Record>, +} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, string|Observable> & Record<`.${string}`, any> +type _fromElsInterfaces= Omit; /** * Just element attributtes * @@ -41,17 +107,28 @@ type AttrsModified= { * There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives. * @private */ -type ElementAttributes= Omit & AttrsModified; +type ElementAttributes= Partial<_fromElsInterfaces & { [K in keyof _fromElsInterfaces]: Observable<_fromElsInterfaces[K], any> } & AttrsModified>; export function classListDeclarative(element: El, classList: AttrsModified["classList"]): El -export function assign(element: El, ...attrs_array: Partial>[]): El +export function assign(element: El, ...attrs_array: ElementAttributes[]): El export function assignAttribute>(element: El, attr: ATT, value: ElementAttributes[ATT]): ElementAttributes[ATT] type ExtendedHTMLElementTagNameMap= ddeHTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap -export function el( +export function el< + TAG extends string, + EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : ddeHTMLElement) +>( tag_name: TAG, - attrs?: string | Partial>, - ...addons: ddeElementAddon[] -): ExtendedHTMLElementTagNameMap[TAG] + attrs?: ElementAttributes, + ...addons: ddeElementAddon[] +): EL +export function el< + TAG extends string, + EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : ddeHTMLElement) +>( + tag_name: TAG, + attrs?: string | Observable, + ...addons: ddeElementAddon[] +): EL export function el( tag_name?: "<>", ): ddeDocumentFragment @@ -63,12 +140,7 @@ export function el< attrs?: A | string, ...addons: ddeElementAddon>[] ): ReturnType - -export function el( - tag_name: string, - attrs?: string | Record, - ...addons: ddeElementAddon[] -): ddeHTMLElement +export { el as createElement } export function elNS( namespace: "http://www.w3.org/2000/svg" @@ -91,6 +163,7 @@ export function elNS( attrs?: string | Record, ...addons: ddeElementAddon[] )=> SupportedElement +export { elNS as createElementNS } export function chainableAppend(el: EL): EL; export function simulateSlots(el: EL): EL @@ -250,71 +323,6 @@ declare global{ "ul": ddeHTMLUListElement; "video": ddeHTMLVideoElement; } - interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend; } - interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend; } - interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend; } - interface ddeHTMLBaseElement extends HTMLBaseElement{ append: ddeAppend; } - interface ddeHTMLQuoteElement extends HTMLQuoteElement{ append: ddeAppend; } - interface ddeHTMLBodyElement extends HTMLBodyElement{ append: ddeAppend; } - interface ddeHTMLBRElement extends HTMLBRElement{ append: ddeAppend; } - interface ddeHTMLButtonElement extends HTMLButtonElement{ append: ddeAppend; } - interface ddeHTMLCanvasElement extends HTMLCanvasElement{ append: ddeAppend; } - interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement{ append: ddeAppend; } - interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } - interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } - interface ddeHTMLDataElement extends HTMLDataElement{ append: ddeAppend; } - interface ddeHTMLDataListElement extends HTMLDataListElement{ append: ddeAppend; } - interface ddeHTMLModElement extends HTMLModElement{ append: ddeAppend; } - interface ddeHTMLDetailsElement extends HTMLDetailsElement{ append: ddeAppend; } - interface ddeHTMLDialogElement extends HTMLDialogElement{ append: ddeAppend; } - interface ddeHTMLDivElement extends HTMLDivElement{ append: ddeAppend; } - interface ddeHTMLDListElement extends HTMLDListElement{ append: ddeAppend; } - interface ddeHTMLEmbedElement extends HTMLEmbedElement{ append: ddeAppend; } - interface ddeHTMLFieldSetElement extends HTMLFieldSetElement{ append: ddeAppend; } - interface ddeHTMLFormElement extends HTMLFormElement{ append: ddeAppend; } - interface ddeHTMLHeadingElement extends HTMLHeadingElement{ append: ddeAppend; } - interface ddeHTMLHeadElement extends HTMLHeadElement{ append: ddeAppend; } - interface ddeHTMLHRElement extends HTMLHRElement{ append: ddeAppend; } - interface ddeHTMLHtmlElement extends HTMLHtmlElement{ append: ddeAppend; } - interface ddeHTMLIFrameElement extends HTMLIFrameElement{ append: ddeAppend; } - interface ddeHTMLImageElement extends HTMLImageElement{ append: ddeAppend; } - interface ddeHTMLInputElement extends HTMLInputElement{ append: ddeAppend; } - interface ddeHTMLLabelElement extends HTMLLabelElement{ append: ddeAppend; } - interface ddeHTMLLegendElement extends HTMLLegendElement{ append: ddeAppend; } - interface ddeHTMLLIElement extends HTMLLIElement{ append: ddeAppend; } - interface ddeHTMLLinkElement extends HTMLLinkElement{ append: ddeAppend; } - interface ddeHTMLMapElement extends HTMLMapElement{ append: ddeAppend; } - interface ddeHTMLMenuElement extends HTMLMenuElement{ append: ddeAppend; } - interface ddeHTMLMetaElement extends HTMLMetaElement{ append: ddeAppend; } - interface ddeHTMLMeterElement extends HTMLMeterElement{ append: ddeAppend; } - interface ddeHTMLObjectElement extends HTMLObjectElement{ append: ddeAppend; } - interface ddeHTMLOListElement extends HTMLOListElement{ append: ddeAppend; } - interface ddeHTMLOptGroupElement extends HTMLOptGroupElement{ append: ddeAppend; } - interface ddeHTMLOptionElement extends HTMLOptionElement{ append: ddeAppend; } - interface ddeHTMLOutputElement extends HTMLOutputElement{ append: ddeAppend; } - interface ddeHTMLParagraphElement extends HTMLParagraphElement{ append: ddeAppend; } - interface ddeHTMLPictureElement extends HTMLPictureElement{ append: ddeAppend; } - interface ddeHTMLPreElement extends HTMLPreElement{ append: ddeAppend; } - interface ddeHTMLProgressElement extends HTMLProgressElement{ append: ddeAppend; } - interface ddeHTMLScriptElement extends HTMLScriptElement{ append: ddeAppend; } - interface ddeHTMLSelectElement extends HTMLSelectElement{ append: ddeAppend; } - interface ddeHTMLSlotElement extends HTMLSlotElement{ append: ddeAppend; } - interface ddeHTMLSourceElement extends HTMLSourceElement{ append: ddeAppend; } - interface ddeHTMLSpanElement extends HTMLSpanElement{ append: ddeAppend; } - interface ddeHTMLStyleElement extends HTMLStyleElement{ append: ddeAppend; } - interface ddeHTMLTableElement extends HTMLTableElement{ append: ddeAppend; } - interface ddeHTMLTableSectionElement extends HTMLTableSectionElement{ append: ddeAppend; } - interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } - interface ddeHTMLTemplateElement extends HTMLTemplateElement{ append: ddeAppend; } - interface ddeHTMLTextAreaElement extends HTMLTextAreaElement{ append: ddeAppend; } - interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } - interface ddeHTMLTimeElement extends HTMLTimeElement{ append: ddeAppend; } - interface ddeHTMLTitleElement extends HTMLTitleElement{ append: ddeAppend; } - interface ddeHTMLTableRowElement extends HTMLTableRowElement{ append: ddeAppend; } - interface ddeHTMLTrackElement extends HTMLTrackElement{ append: ddeAppend; } - interface ddeHTMLUListElement extends HTMLUListElement{ append: ddeAppend; } - interface ddeHTMLVideoElement extends HTMLVideoElement{ append: ddeAppend; } - interface ddeSVGElementTagNameMap { "a": ddeSVGAElement; "animate": ddeSVGAnimateElement; @@ -380,131 +388,132 @@ declare global{ "use": ddeSVGUseElement; "view": ddeSVGViewElement; } - interface ddeSVGAElement extends SVGAElement{ append: ddeAppend; } - interface ddeSVGAnimateElement extends SVGAnimateElement{ append: ddeAppend; } - interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement{ append: ddeAppend; } - interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement{ append: ddeAppend; } - interface ddeSVGCircleElement extends SVGCircleElement{ append: ddeAppend; } - interface ddeSVGClipPathElement extends SVGClipPathElement{ append: ddeAppend; } - interface ddeSVGDefsElement extends SVGDefsElement{ append: ddeAppend; } - interface ddeSVGDescElement extends SVGDescElement{ append: ddeAppend; } - interface ddeSVGEllipseElement extends SVGEllipseElement{ append: ddeAppend; } - interface ddeSVGFEBlendElement extends SVGFEBlendElement{ append: ddeAppend; } - interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement{ append: ddeAppend; } - interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement{ append: ddeAppend; } - interface ddeSVGFECompositeElement extends SVGFECompositeElement{ append: ddeAppend; } - interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement{ append: ddeAppend; } - interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement{ append: ddeAppend; } - interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement{ append: ddeAppend; } - interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement{ append: ddeAppend; } - interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement{ append: ddeAppend; } - interface ddeSVGFEFloodElement extends SVGFEFloodElement{ append: ddeAppend; } - interface ddeSVGFEFuncAElement extends SVGFEFuncAElement{ append: ddeAppend; } - interface ddeSVGFEFuncBElement extends SVGFEFuncBElement{ append: ddeAppend; } - interface ddeSVGFEFuncGElement extends SVGFEFuncGElement{ append: ddeAppend; } - interface ddeSVGFEFuncRElement extends SVGFEFuncRElement{ append: ddeAppend; } - interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement{ append: ddeAppend; } - interface ddeSVGFEImageElement extends SVGFEImageElement{ append: ddeAppend; } - interface ddeSVGFEMergeElement extends SVGFEMergeElement{ append: ddeAppend; } - interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement{ append: ddeAppend; } - interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement{ append: ddeAppend; } - interface ddeSVGFEOffsetElement extends SVGFEOffsetElement{ append: ddeAppend; } - interface ddeSVGFEPointLightElement extends SVGFEPointLightElement{ append: ddeAppend; } - interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement{ append: ddeAppend; } - interface ddeSVGFESpotLightElement extends SVGFESpotLightElement{ append: ddeAppend; } - interface ddeSVGFETileElement extends SVGFETileElement{ append: ddeAppend; } - interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement{ append: ddeAppend; } - interface ddeSVGFilterElement extends SVGFilterElement{ append: ddeAppend; } - interface ddeSVGForeignObjectElement extends SVGForeignObjectElement{ append: ddeAppend; } - interface ddeSVGGElement extends SVGGElement{ append: ddeAppend; } - interface ddeSVGImageElement extends SVGImageElement{ append: ddeAppend; } - interface ddeSVGLineElement extends SVGLineElement{ append: ddeAppend; } - interface ddeSVGLinearGradientElement extends SVGLinearGradientElement{ append: ddeAppend; } - interface ddeSVGMarkerElement extends SVGMarkerElement{ append: ddeAppend; } - interface ddeSVGMaskElement extends SVGMaskElement{ append: ddeAppend; } - interface ddeSVGMetadataElement extends SVGMetadataElement{ append: ddeAppend; } - interface ddeSVGMPathElement extends SVGMPathElement{ append: ddeAppend; } - interface ddeSVGPathElement extends SVGPathElement{ append: ddeAppend; } - interface ddeSVGPatternElement extends SVGPatternElement{ append: ddeAppend; } - interface ddeSVGPolygonElement extends SVGPolygonElement{ append: ddeAppend; } - interface ddeSVGPolylineElement extends SVGPolylineElement{ append: ddeAppend; } - interface ddeSVGRadialGradientElement extends SVGRadialGradientElement{ append: ddeAppend; } - interface ddeSVGRectElement extends SVGRectElement{ append: ddeAppend; } - interface ddeSVGScriptElement extends SVGScriptElement{ append: ddeAppend; } - interface ddeSVGSetElement extends SVGSetElement{ append: ddeAppend; } - interface ddeSVGStopElement extends SVGStopElement{ append: ddeAppend; } - interface ddeSVGStyleElement extends SVGStyleElement{ append: ddeAppend; } - interface ddeSVGSVGElement extends SVGSVGElement{ append: ddeAppend; } - interface ddeSVGSwitchElement extends SVGSwitchElement{ append: ddeAppend; } - interface ddeSVGSymbolElement extends SVGSymbolElement{ append: ddeAppend; } - interface ddeSVGTextElement extends SVGTextElement{ append: ddeAppend; } - interface ddeSVGTextPathElement extends SVGTextPathElement{ append: ddeAppend; } - interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend; } - interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend; } - interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend; } - interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend; } } -export type Observable= (set?: V)=> V & A; -type Action= (this: { value: V }, ...a: any[])=> typeof observable._ | void; -type SymbolOnclear= Symbol; -type SymbolObservable= Symbol; -type Actions= Record>; -interface observable{ - _: Symbol - /** - * Simple example: - * ```js - * const hello= S("Hello Observable"); - * ``` - * …simple todo observable: - * ```js - * const todos= S([], { - * add(v){ this.value.push(S(v)); }, - * remove(i){ this.value.splice(i, 1); }, - * [S.symbols.onclear](){ S.clear(...this.value); }, - * }); - * ``` - * …computed observable: - * ```js - * const name= S("Jan"); - * const surname= S("Andrle"); - * const fullname= S(()=> name()+" "+surname()); - * ``` - * @param value Initial observable value. Or function computing value from other observables. - * @param actions Use to define actions on the observable. Such as add item to the array. - * There is also a reserved function `S.symbol.onclear` which is called when the observable is cleared - * by `S.clear`. - * */ - >(value: V, actions?: A): Observable; - /** - * Computations observable. This creates a observable which is computed from other observables. - * */ - (computation: ()=> V): Observable - action>, A extends (S extends Observable ? A : never), N extends keyof A>( - observable: S, - name: N, - ...params: A[N] extends (...args: infer P)=> any ? P : never - ): void; - clear(...observables: Observable[]): void; - on(observable: Observable, onchange: (a: T)=> void, options?: AddEventListenerOptions): void; - symbols: { - observable: SymbolObservable; - onclear: SymbolOnclear; - } - /** - * Reactive element, which is rendered based on the given observable. - * ```js - * S.el(observable, value=> value ? el("b", "True") : el("i", "False")); - * S.el(listS, list=> list.map(li=> el("li", li))); - * ``` - * */ - el(observable: Observable, el: (v: S)=> Element | Element[]): DocumentFragment; - attribute(name: string, initial?: string): Observable; -} -export const observable: observable; -export const O: observable; -declare global { - type ddeObservable= Observable; - type ddeActions= Actions -} \ No newline at end of file +interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend; } +interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend; } +interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend; } +interface ddeHTMLBaseElement extends HTMLBaseElement{ append: ddeAppend; } +interface ddeHTMLQuoteElement extends HTMLQuoteElement{ append: ddeAppend; } +interface ddeHTMLBodyElement extends HTMLBodyElement{ append: ddeAppend; } +interface ddeHTMLBRElement extends HTMLBRElement{ append: ddeAppend; } +interface ddeHTMLButtonElement extends HTMLButtonElement{ append: ddeAppend; } +interface ddeHTMLCanvasElement extends HTMLCanvasElement{ append: ddeAppend; } +interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement{ append: ddeAppend; } +interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } +interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } +interface ddeHTMLDataElement extends HTMLDataElement{ append: ddeAppend; } +interface ddeHTMLDataListElement extends HTMLDataListElement{ append: ddeAppend; } +interface ddeHTMLModElement extends HTMLModElement{ append: ddeAppend; } +interface ddeHTMLDetailsElement extends HTMLDetailsElement{ append: ddeAppend; } +interface ddeHTMLDialogElement extends HTMLDialogElement{ append: ddeAppend; } +interface ddeHTMLDivElement extends HTMLDivElement{ append: ddeAppend; } +interface ddeHTMLDListElement extends HTMLDListElement{ append: ddeAppend; } +interface ddeHTMLEmbedElement extends HTMLEmbedElement{ append: ddeAppend; } +interface ddeHTMLFieldSetElement extends HTMLFieldSetElement{ append: ddeAppend; } +interface ddeHTMLFormElement extends HTMLFormElement{ append: ddeAppend; } +interface ddeHTMLHeadingElement extends HTMLHeadingElement{ append: ddeAppend; } +interface ddeHTMLHeadElement extends HTMLHeadElement{ append: ddeAppend; } +interface ddeHTMLHRElement extends HTMLHRElement{ append: ddeAppend; } +interface ddeHTMLHtmlElement extends HTMLHtmlElement{ append: ddeAppend; } +interface ddeHTMLIFrameElement extends HTMLIFrameElement{ append: ddeAppend; } +interface ddeHTMLImageElement extends HTMLImageElement{ append: ddeAppend; } +interface ddeHTMLInputElement extends HTMLInputElement{ append: ddeAppend; } +interface ddeHTMLLabelElement extends HTMLLabelElement{ append: ddeAppend; } +interface ddeHTMLLegendElement extends HTMLLegendElement{ append: ddeAppend; } +interface ddeHTMLLIElement extends HTMLLIElement{ append: ddeAppend; } +interface ddeHTMLLinkElement extends HTMLLinkElement{ append: ddeAppend; } +interface ddeHTMLMapElement extends HTMLMapElement{ append: ddeAppend; } +interface ddeHTMLMenuElement extends HTMLMenuElement{ append: ddeAppend; } +interface ddeHTMLMetaElement extends HTMLMetaElement{ append: ddeAppend; } +interface ddeHTMLMeterElement extends HTMLMeterElement{ append: ddeAppend; } +interface ddeHTMLObjectElement extends HTMLObjectElement{ append: ddeAppend; } +interface ddeHTMLOListElement extends HTMLOListElement{ append: ddeAppend; } +interface ddeHTMLOptGroupElement extends HTMLOptGroupElement{ append: ddeAppend; } +interface ddeHTMLOptionElement extends HTMLOptionElement{ append: ddeAppend; } +interface ddeHTMLOutputElement extends HTMLOutputElement{ append: ddeAppend; } +interface ddeHTMLParagraphElement extends HTMLParagraphElement{ append: ddeAppend; } +interface ddeHTMLPictureElement extends HTMLPictureElement{ append: ddeAppend; } +interface ddeHTMLPreElement extends HTMLPreElement{ append: ddeAppend; } +interface ddeHTMLProgressElement extends HTMLProgressElement{ append: ddeAppend; } +interface ddeHTMLScriptElement extends HTMLScriptElement{ append: ddeAppend; } +interface ddeHTMLSelectElement extends HTMLSelectElement{ append: ddeAppend; } +interface ddeHTMLSlotElement extends HTMLSlotElement{ append: ddeAppend; } +interface ddeHTMLSourceElement extends HTMLSourceElement{ append: ddeAppend; } +interface ddeHTMLSpanElement extends HTMLSpanElement{ append: ddeAppend; } +interface ddeHTMLStyleElement extends HTMLStyleElement{ append: ddeAppend; } +interface ddeHTMLTableElement extends HTMLTableElement{ append: ddeAppend; } +interface ddeHTMLTableSectionElement extends HTMLTableSectionElement{ append: ddeAppend; } +interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } +interface ddeHTMLTemplateElement extends HTMLTemplateElement{ append: ddeAppend; } +interface ddeHTMLTextAreaElement extends HTMLTextAreaElement{ append: ddeAppend; } +interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } +interface ddeHTMLTimeElement extends HTMLTimeElement{ append: ddeAppend; } +interface ddeHTMLTitleElement extends HTMLTitleElement{ append: ddeAppend; } +interface ddeHTMLTableRowElement extends HTMLTableRowElement{ append: ddeAppend; } +interface ddeHTMLTrackElement extends HTMLTrackElement{ append: ddeAppend; } +interface ddeHTMLUListElement extends HTMLUListElement{ append: ddeAppend; } +interface ddeHTMLVideoElement extends HTMLVideoElement{ append: ddeAppend; } +interface ddeSVGAElement extends SVGAElement{ append: ddeAppend; } +interface ddeSVGAnimateElement extends SVGAnimateElement{ append: ddeAppend; } +interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement{ append: ddeAppend; } +interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement{ append: ddeAppend; } +interface ddeSVGCircleElement extends SVGCircleElement{ append: ddeAppend; } +interface ddeSVGClipPathElement extends SVGClipPathElement{ append: ddeAppend; } +interface ddeSVGDefsElement extends SVGDefsElement{ append: ddeAppend; } +interface ddeSVGDescElement extends SVGDescElement{ append: ddeAppend; } +interface ddeSVGEllipseElement extends SVGEllipseElement{ append: ddeAppend; } +interface ddeSVGFEBlendElement extends SVGFEBlendElement{ append: ddeAppend; } +interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement{ append: ddeAppend; } +interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement{ append: ddeAppend; } +interface ddeSVGFECompositeElement extends SVGFECompositeElement{ append: ddeAppend; } +interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement{ append: ddeAppend; } +interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement{ append: ddeAppend; } +interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement{ append: ddeAppend; } +interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement{ append: ddeAppend; } +interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement{ append: ddeAppend; } +interface ddeSVGFEFloodElement extends SVGFEFloodElement{ append: ddeAppend; } +interface ddeSVGFEFuncAElement extends SVGFEFuncAElement{ append: ddeAppend; } +interface ddeSVGFEFuncBElement extends SVGFEFuncBElement{ append: ddeAppend; } +interface ddeSVGFEFuncGElement extends SVGFEFuncGElement{ append: ddeAppend; } +interface ddeSVGFEFuncRElement extends SVGFEFuncRElement{ append: ddeAppend; } +interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement{ append: ddeAppend; } +interface ddeSVGFEImageElement extends SVGFEImageElement{ append: ddeAppend; } +interface ddeSVGFEMergeElement extends SVGFEMergeElement{ append: ddeAppend; } +interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement{ append: ddeAppend; } +interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement{ append: ddeAppend; } +interface ddeSVGFEOffsetElement extends SVGFEOffsetElement{ append: ddeAppend; } +interface ddeSVGFEPointLightElement extends SVGFEPointLightElement{ append: ddeAppend; } +interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement{ append: ddeAppend; } +interface ddeSVGFESpotLightElement extends SVGFESpotLightElement{ append: ddeAppend; } +interface ddeSVGFETileElement extends SVGFETileElement{ append: ddeAppend; } +interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement{ append: ddeAppend; } +interface ddeSVGFilterElement extends SVGFilterElement{ append: ddeAppend; } +interface ddeSVGForeignObjectElement extends SVGForeignObjectElement{ append: ddeAppend; } +interface ddeSVGGElement extends SVGGElement{ append: ddeAppend; } +interface ddeSVGImageElement extends SVGImageElement{ append: ddeAppend; } +interface ddeSVGLineElement extends SVGLineElement{ append: ddeAppend; } +interface ddeSVGLinearGradientElement extends SVGLinearGradientElement{ append: ddeAppend; } +interface ddeSVGMarkerElement extends SVGMarkerElement{ append: ddeAppend; } +interface ddeSVGMaskElement extends SVGMaskElement{ append: ddeAppend; } +interface ddeSVGMetadataElement extends SVGMetadataElement{ append: ddeAppend; } +interface ddeSVGMPathElement extends SVGMPathElement{ append: ddeAppend; } +interface ddeSVGPathElement extends SVGPathElement{ append: ddeAppend; } +interface ddeSVGPatternElement extends SVGPatternElement{ append: ddeAppend; } +interface ddeSVGPolygonElement extends SVGPolygonElement{ append: ddeAppend; } +interface ddeSVGPolylineElement extends SVGPolylineElement{ append: ddeAppend; } +interface ddeSVGRadialGradientElement extends SVGRadialGradientElement{ append: ddeAppend; } +interface ddeSVGRectElement extends SVGRectElement{ append: ddeAppend; } +interface ddeSVGScriptElement extends SVGScriptElement{ append: ddeAppend; } +interface ddeSVGSetElement extends SVGSetElement{ append: ddeAppend; } +interface ddeSVGStopElement extends SVGStopElement{ append: ddeAppend; } +interface ddeSVGStyleElement extends SVGStyleElement{ append: ddeAppend; } +interface ddeSVGSVGElement extends SVGSVGElement{ append: ddeAppend; } +interface ddeSVGSwitchElement extends SVGSwitchElement{ append: ddeAppend; } +interface ddeSVGSymbolElement extends SVGSymbolElement{ append: ddeAppend; } +interface ddeSVGTextElement extends SVGTextElement{ append: ddeAppend; } +interface ddeSVGTextPathElement extends SVGTextPathElement{ append: ddeAppend; } +interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend; } +interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend; } +interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend; } +interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend; } \ No newline at end of file diff --git a/dist/esm-with-observables.js b/dist/esm-with-observables.js index d1da246..5274bff 100644 --- a/dist/esm-with-observables.js +++ b/dist/esm-with-observables.js @@ -1,4 +1,4 @@ -var A={isObservable(e){return!1},processReactiveAttribute(e,t,n,r){return n}};function T(e,t=!0){return t?Object.assign(A,e):(Object.setPrototypeOf(e,A),e)}function C(e){return A.isPrototypeOf(e)&&e!==A?e:A}function x(e){return typeof e>"u"}function B(e){let t=typeof e;return t!=="object"?t:e===null?"null":Object.prototype.toString.call(e)}function N(e,t){if(!e||!(e instanceof AbortSignal))return!0;if(!e.aborted)return e.addEventListener("abort",t),function(){e.removeEventListener("abort",t)}}var $={setDeleteAttr:ee,ssr:""};function ee(e,t,n){if(Reflect.set(e,t,n),!!x(n)){if(Reflect.deleteProperty(e,t),e instanceof HTMLElement&&e.getAttribute(t)==="undefined")return e.removeAttribute(t);if(Reflect.get(e,t)==="undefined")return Reflect.set(e,t,"")}}var E=[{scope:document.body,host:e=>e?e(document.body):document.body,custom_element:!1,prevent:!0}],b={get current(){return E[E.length-1]},get host(){return this.current.host},preventDefault(){let{current:e}=this;return e.prevent=!0,e},get state(){return[...E]},push(e={}){return E.push(Object.assign({},this.current,{prevent:!1},e))},pushRoot(){return E.push(E[0])},pop(){if(E.length!==1)return E.pop()}};function H(...e){return this.appendOriginal(...e),this}function te(e){return e.append===H||(e.appendOriginal=e.append,e.append=H),e}var j;function y(e,t,...n){let r=C(this),o=0,c,s;switch((Object(t)!==t||r.isObservable(t))&&(t={textContent:t}),!0){case typeof e=="function":{o=1,b.push({scope:e,host:(...l)=>l.length?(o===1?n.unshift(...l):l.forEach(v=>v(s)),void 0):s}),c=e(t||void 0);let d=c instanceof DocumentFragment;if(c.nodeName==="#comment")break;let u=y.mark({type:"component",name:e.name,host:d?"this":"parentElement"});c.prepend(u),d&&(s=u);break}case e==="#text":c=P.call(this,document.createTextNode(""),t);break;case(e==="<>"||!e):c=P.call(this,document.createDocumentFragment(),t);break;case!!j:c=P.call(this,document.createElementNS(j,e),t);break;case!c:c=P.call(this,document.createElement(e),t)}return te(c),s||(s=c),n.forEach(d=>d(s)),o&&b.pop(),o=2,c}function _e(e){let t=Symbol.for("default"),n=Array.from(e.querySelectorAll("slot")).reduce((o,c)=>Reflect.set(o,c.name||t,c)&&o,{}),r=Reflect.has(n,t);return e.append=new Proxy(e.append,{apply(o,c,s){if(!s.length)return e;let d=document.createDocumentFragment();for(let u of s){if(!u||!u.slot){r&&d.appendChild(u);continue}let l=u.slot,v=n[l];O(u,"remove","slot"),v&&(v.replaceWith(u),Reflect.deleteProperty(n,l))}return r&&(n[t].replaceWith(d),Reflect.deleteProperty(n,t)),Object.values(n).forEach(u=>u.replaceWith(y().append(...Array.from(u.childNodes)))),e}}),e}y.mark=function(e,t=!1){e=Object.entries(e).map(([o,c])=>o+`="${c}"`).join(" ");let n=t?"":"/",r=document.createComment(``);return t||(r.end=document.createComment("")),r};function Ee(e){let t=this;return function(...r){j=e;let o=y.call(t,...r);return j=void 0,o}}var{setDeleteAttr:I}=$,L=new WeakMap;function P(e,...t){if(!t.length)return e;L.set(e,G(e,this));for(let[n,r]of Object.entries(Object.assign({},...t)))Z.call(this,e,n,r);return L.delete(e),e}function Z(e,t,n){let{setRemoveAttr:r,s:o}=G(e,this),c=this;n=o.processReactiveAttribute(e,t,n,(d,u)=>Z.call(c,e,d,u));let[s]=t;if(s==="=")return r(t.slice(1),n);if(s===".")return J(e,t.slice(1),n);if(/(aria|data)([A-Z])/.test(t))return t=t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),r(t,n);switch(t==="className"&&(t="class"),t){case"xlink:href":return r(t,n,"http://www.w3.org/1999/xlink");case"textContent":return I(e,t,n);case"style":if(typeof n!="object")break;case"dataset":return F(o,n,J.bind(null,e[t]));case"ariaset":return F(o,n,(d,u)=>r("aria-"+d,u));case"classList":return ne.call(c,e,n)}return re(e,t)?I(e,t,n):r(t,n)}function G(e,t){if(L.has(e))return L.get(e);let r=(e instanceof SVGElement?ce:oe).bind(null,e,"Attribute"),o=C(t);return{setRemoveAttr:r,s:o}}function ne(e,t){let n=C(this);return F(n,t,(r,o)=>e.classList.toggle(r,o===-1?void 0:!!o)),e}function xe(e){return Array.from(e.children).forEach(t=>t.remove()),e}function O(e,t,n,r){return e instanceof HTMLElement?e[t+"Attribute"](n,r):e[t+"AttributeNS"](null,n,r)}function re(e,t){if(!Reflect.has(e,t))return!1;let n=V(e,t);return!x(n.set)}function V(e,t){if(e=Object.getPrototypeOf(e),!e)return{};let n=Object.getOwnPropertyDescriptor(e,t);return n||V(e,t)}function F(e,t,n){if(!(typeof t!="object"||t===null))return Object.entries(t).forEach(function([o,c]){o&&(c=e.processReactiveAttribute(t,o,c,n),n(o,c))})}function K(e){return Array.isArray(e)?e.filter(Boolean).join(" "):e}function oe(e,t,n,r){return e[(x(r)?"remove":"set")+t](n,K(r))}function ce(e,t,n,r,o=null){return e[(x(r)?"remove":"set")+t+"NS"](o,n,K(r))}function J(e,t,n){if(Reflect.set(e,t,n),!!x(n))return Reflect.deleteProperty(e,t)}function we(e,t,n){return t||(t={}),function(o,...c){n&&(c.unshift(o),o=typeof n=="function"?n():n);let s=c.length?new CustomEvent(e,Object.assign({detail:c[0]},t)):new Event(e,t);return o.dispatchEvent(s)}}function _(e,t,n){return function(o){return o.addEventListener(e,t,n),o}}var D=ie(),se=new WeakSet;_.connected=function(e,t){let{custom_element:n}=b.current,r="connected";return typeof t!="object"&&(t={}),t.once=!0,function(c){n&&(c=n);let s="dde:"+r;return c.addEventListener(s,e,t),c.__dde_lifecycleToEvents?c:c.isConnected?(c.dispatchEvent(new Event(s)),c):(N(t.signal,()=>D.offConnected(c,e))&&D.onConnected(c,e),c)}};_.disconnected=function(e,t){let{custom_element:n}=b.current,r="disconnected";return typeof t!="object"&&(t={}),t.once=!0,function(c){n&&(c=n);let s="dde:"+r;return c.addEventListener(s,e,t),c.__dde_lifecycleToEvents||N(t.signal,()=>D.offDisconnected(c,e))&&D.onDisconnected(c,e),c}};var z=new WeakMap;_.disconnectedAsAbort=function(e){if(z.has(e))return z.get(e);let t=new AbortController;return z.set(e,t),e(_.disconnected(()=>t.abort())),t};_.attributeChanged=function(e,t){let n="attributeChanged";return typeof t!="object"&&(t={}),function(o){let c="dde:"+n;if(o.addEventListener(c,e,t),o.__dde_lifecycleToEvents||se.has(o))return o;let s=new MutationObserver(function(u){for(let{attributeName:l,target:v}of u)v.dispatchEvent(new CustomEvent(c,{detail:[l,v.getAttribute(l)]}))});return N(t.signal,()=>s.disconnect())&&s.observe(o,{attributes:!0}),o}};function ie(){let e=new Map,t=!1,n=new MutationObserver(function(i){for(let f of i)if(f.type==="childList"){if(l(f.addedNodes,!0)){s();continue}v(f.removedNodes,!0)&&s()}});return{onConnected(i,f){c();let a=o(i);a.connected.has(f)||(a.connected.add(f),a.length_c+=1)},offConnected(i,f){if(!e.has(i))return;let a=e.get(i);a.connected.has(f)&&(a.connected.delete(f),a.length_c-=1,r(i,a))},onDisconnected(i,f){c();let a=o(i);a.disconnected.has(f)||(a.disconnected.add(f),a.length_d+=1)},offDisconnected(i,f){if(!e.has(i))return;let a=e.get(i);a.disconnected.has(f)&&(a.disconnected.delete(f),a.length_d-=1,r(i,a))}};function r(i,f){f.length_c||f.length_d||(e.delete(i),s())}function o(i){if(e.has(i))return e.get(i);let f={connected:new WeakSet,length_c:0,disconnected:new WeakSet,length_d:0};return e.set(i,f),f}function c(){t||(t=!0,n.observe(document.body,{childList:!0,subtree:!0}))}function s(){!t||e.size||(t=!1,n.disconnect())}function d(){return new Promise(function(i){(requestIdleCallback||requestAnimationFrame)(i)})}async function u(i){e.size>30&&await d();let f=[];if(!(i instanceof Node))return f;for(let a of e.keys())a===i||!(a instanceof Node)||i.contains(a)&&f.push(a);return f}function l(i,f){let a=!1;for(let g of i){if(f&&u(g).then(l),!e.has(g))continue;let w=e.get(g);w.length_c&&(g.dispatchEvent(new Event("dde:connected")),w.connected=new WeakSet,w.length_c=0,w.length_d||e.delete(g),a=!0)}return a}function v(i,f){let a=!1;for(let g of i)f&&u(g).then(v),!(!e.has(g)||!e.get(g).length_d)&&(g.dispatchEvent(new Event("dde:disconnected")),e.delete(g),a=!0);return a}}var p=Symbol.for("observable");function W(e){try{return Reflect.has(e,p)}catch{return!1}}var M=[],h=new WeakMap;function m(e,t){if(typeof e!="function")return Q(e,t);if(W(e))return e;let n=Q(),r=function(){let[o,...c]=h.get(r);if(h.set(r,new Set([o])),M.push(r),n(e()),M.pop(),!c.length)return;let s=h.get(r);for(let d of c)s.has(d)||S(d,r)};return h.set(n[p],r),h.set(r,new Set([n])),r(),n}m.action=function(e,t,...n){let r=e[p],{actions:o}=r;if(!o||!Reflect.has(o,t))throw new Error(`'${e}' has no action with name '${t}'!`);if(o[t].apply(r,n),r.skip)return Reflect.deleteProperty(r,"skip");r.listeners.forEach(c=>c(r.value))};m.on=function e(t,n,r={}){let{signal:o}=r;if(!(o&&o.aborted)){if(Array.isArray(t))return t.forEach(c=>e(c,n,r));U(t,n),o&&o.addEventListener("abort",()=>S(t,n))}};m.symbols={observable:p,onclear:Symbol.for("Observable.onclear")};m.clear=function(...e){for(let n of e){Reflect.deleteProperty(n,"toJSON");let r=n[p];r.onclear.forEach(o=>o.call(r)),t(n,r),Reflect.deleteProperty(n,p)}function t(n,r){r.listeners.forEach(o=>{if(r.listeners.delete(o),!h.has(o))return;let c=h.get(o);c.delete(n),!(c.size>1)&&(n.clear(...c),h.delete(o))})}};var k="__dde_reactive";m.el=function(e,t){let n=y.mark({type:"reactive"},!1),r=n.end,o=document.createDocumentFragment();o.append(n,r);let{current:c}=b,s=d=>{if(!n.parentNode||!r.parentNode)return S(e,s);b.push(c);let u=t(d);b.pop(),Array.isArray(u)||(u=[u]);let l=n;for(;(l=n.nextSibling)!==r;)l.remove();n.after(...u)};return U(e,s),Y(e,s,n,t),s(e()),o};var R="__dde_attributes";m.attribute=function(e,t=null){let n=m(t),r;return b.host(o=>{if(r=o,O(r,"has",e)?n(O(r,"get",e)):t!==null&&O(r,"set",e,t),o[R]){o[R][e]=n;return}r[R]={[e]:n},_.attributeChanged(function({detail:s}){/*! This maps attributes to observables (`S.attribute`). +var A={isObservable(e){return!1},processReactiveAttribute(e,t,n,r){return n}};function T(e,t=!0){return t?Object.assign(A,e):(Object.setPrototypeOf(e,A),e)}function C(e){return A.isPrototypeOf(e)&&e!==A?e:A}function x(e){return typeof e>"u"}function B(e){let t=typeof e;return t!=="object"?t:e===null?"null":Object.prototype.toString.call(e)}function N(e,t){if(!e||!(e instanceof AbortSignal))return!0;if(!e.aborted)return e.addEventListener("abort",t),function(){e.removeEventListener("abort",t)}}var $={setDeleteAttr:ee,ssr:""};function ee(e,t,n){if(Reflect.set(e,t,n),!!x(n)){if(Reflect.deleteProperty(e,t),e instanceof HTMLElement&&e.getAttribute(t)==="undefined")return e.removeAttribute(t);if(Reflect.get(e,t)==="undefined")return Reflect.set(e,t,"")}}var E=[{scope:document.body,host:e=>e?e(document.body):document.body,custom_element:!1,prevent:!0}],b={get current(){return E[E.length-1]},get host(){return this.current.host},preventDefault(){let{current:e}=this;return e.prevent=!0,e},get state(){return[...E]},push(e={}){return E.push(Object.assign({},this.current,{prevent:!1},e))},pushRoot(){return E.push(E[0])},pop(){if(E.length!==1)return E.pop()}};function H(...e){return this.appendOriginal(...e),this}function te(e){return e.append===H||(e.appendOriginal=e.append,e.append=H),e}var j;function y(e,t,...n){let r=C(this),o=0,c,s;switch((Object(t)!==t||r.isObservable(t))&&(t={textContent:t}),!0){case typeof e=="function":{o=1,b.push({scope:e,host:(...l)=>l.length?(o===1?n.unshift(...l):l.forEach(v=>v(s)),void 0):s}),c=e(t||void 0);let d=c instanceof DocumentFragment;if(c.nodeName==="#comment")break;let u=y.mark({type:"component",name:e.name,host:d?"this":"parentElement"});c.prepend(u),d&&(s=u);break}case e==="#text":c=P.call(this,document.createTextNode(""),t);break;case(e==="<>"||!e):c=P.call(this,document.createDocumentFragment(),t);break;case!!j:c=P.call(this,document.createElementNS(j,e),t);break;case!c:c=P.call(this,document.createElement(e),t)}return te(c),s||(s=c),n.forEach(d=>d(s)),o&&b.pop(),o=2,c}function _e(e){let t=Symbol.for("default"),n=Array.from(e.querySelectorAll("slot")).reduce((o,c)=>Reflect.set(o,c.name||t,c)&&o,{}),r=Reflect.has(n,t);return e.append=new Proxy(e.append,{apply(o,c,s){if(!s.length)return e;let d=document.createDocumentFragment();for(let u of s){if(!u||!u.slot){r&&d.appendChild(u);continue}let l=u.slot,v=n[l];O(u,"remove","slot"),v&&(v.replaceWith(u),Reflect.deleteProperty(n,l))}return r&&(n[t].replaceWith(d),Reflect.deleteProperty(n,t)),Object.values(n).forEach(u=>u.replaceWith(y().append(...Array.from(u.childNodes)))),e}}),e}y.mark=function(e,t=!1){e=Object.entries(e).map(([o,c])=>o+`="${c}"`).join(" ");let n=t?"":"/",r=document.createComment(``);return t||(r.end=document.createComment("")),r};function Ee(e){let t=this;return function(...r){j=e;let o=y.call(t,...r);return j=void 0,o}}var{setDeleteAttr:I}=$,L=new WeakMap;function P(e,...t){if(!t.length)return e;L.set(e,G(e,this));for(let[n,r]of Object.entries(Object.assign({},...t)))Z.call(this,e,n,r);return L.delete(e),e}function Z(e,t,n){let{setRemoveAttr:r,s:o}=G(e,this),c=this;n=o.processReactiveAttribute(e,t,n,(d,u)=>Z.call(c,e,d,u));let[s]=t;if(s==="=")return r(t.slice(1),n);if(s===".")return J(e,t.slice(1),n);if(/(aria|data)([A-Z])/.test(t))return t=t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),r(t,n);switch(t==="className"&&(t="class"),t){case"xlink:href":return r(t,n,"http://www.w3.org/1999/xlink");case"textContent":return I(e,t,n);case"style":if(typeof n!="object")break;case"dataset":return F(o,n,J.bind(null,e[t]));case"ariaset":return F(o,n,(d,u)=>r("aria-"+d,u));case"classList":return ne.call(c,e,n)}return re(e,t)?I(e,t,n):r(t,n)}function G(e,t){if(L.has(e))return L.get(e);let r=(e instanceof SVGElement?ce:oe).bind(null,e,"Attribute"),o=C(t);return{setRemoveAttr:r,s:o}}function ne(e,t){let n=C(this);return F(n,t,(r,o)=>e.classList.toggle(r,o===-1?void 0:!!o)),e}function xe(e){return Array.from(e.children).forEach(t=>t.remove()),e}function O(e,t,n,r){return e instanceof HTMLElement?e[t+"Attribute"](n,r):e[t+"AttributeNS"](null,n,r)}function re(e,t){if(!Reflect.has(e,t))return!1;let n=V(e,t);return!x(n.set)}function V(e,t){if(e=Object.getPrototypeOf(e),!e)return{};let n=Object.getOwnPropertyDescriptor(e,t);return n||V(e,t)}function F(e,t,n){if(!(typeof t!="object"||t===null))return Object.entries(t).forEach(function([o,c]){o&&(c=e.processReactiveAttribute(t,o,c,n),n(o,c))})}function K(e){return Array.isArray(e)?e.filter(Boolean).join(" "):e}function oe(e,t,n,r){return e[(x(r)?"remove":"set")+t](n,K(r))}function ce(e,t,n,r,o=null){return e[(x(r)?"remove":"set")+t+"NS"](o,n,K(r))}function J(e,t,n){if(Reflect.set(e,t,n),!!x(n))return Reflect.deleteProperty(e,t)}function we(e,t,n){return t||(t={}),function(o,...c){n&&(c.unshift(o),o=typeof n=="function"?n():n);let s=c.length?new CustomEvent(e,Object.assign({detail:c[0]},t)):new Event(e,t);return o.dispatchEvent(s)}}function _(e,t,n){return function(o){return o.addEventListener(e,t,n),o}}var D=ie(),se=new WeakSet;_.connected=function(e,t){let{custom_element:n}=b.current,r="connected";return typeof t!="object"&&(t={}),t.once=!0,function(c){n&&(c=n);let s="dde:"+r;return c.addEventListener(s,e,t),c.__dde_lifecycleToEvents?c:c.isConnected?(c.dispatchEvent(new Event(s)),c):(N(t.signal,()=>D.offConnected(c,e))&&D.onConnected(c,e),c)}};_.disconnected=function(e,t){let{custom_element:n}=b.current,r="disconnected";return typeof t!="object"&&(t={}),t.once=!0,function(c){n&&(c=n);let s="dde:"+r;return c.addEventListener(s,e,t),c.__dde_lifecycleToEvents||N(t.signal,()=>D.offDisconnected(c,e))&&D.onDisconnected(c,e),c}};var z=new WeakMap;_.disconnectedAsAbort=function(e){if(z.has(e))return z.get(e);let t=new AbortController;return z.set(e,t),e(_.disconnected(()=>t.abort())),t};_.attributeChanged=function(e,t){let n="attributeChanged";return typeof t!="object"&&(t={}),function(o){let c="dde:"+n;if(o.addEventListener(c,e,t),o.__dde_lifecycleToEvents||se.has(o))return o;let s=new MutationObserver(function(u){for(let{attributeName:l,target:v}of u)v.dispatchEvent(new CustomEvent(c,{detail:[l,v.getAttribute(l)]}))});return N(t.signal,()=>s.disconnect())&&s.observe(o,{attributes:!0}),o}};function ie(){let e=new Map,t=!1,n=new MutationObserver(function(i){for(let f of i)if(f.type==="childList"){if(l(f.addedNodes,!0)){s();continue}v(f.removedNodes,!0)&&s()}});return{onConnected(i,f){c();let a=o(i);a.connected.has(f)||(a.connected.add(f),a.length_c+=1)},offConnected(i,f){if(!e.has(i))return;let a=e.get(i);a.connected.has(f)&&(a.connected.delete(f),a.length_c-=1,r(i,a))},onDisconnected(i,f){c();let a=o(i);a.disconnected.has(f)||(a.disconnected.add(f),a.length_d+=1)},offDisconnected(i,f){if(!e.has(i))return;let a=e.get(i);a.disconnected.has(f)&&(a.disconnected.delete(f),a.length_d-=1,r(i,a))}};function r(i,f){f.length_c||f.length_d||(e.delete(i),s())}function o(i){if(e.has(i))return e.get(i);let f={connected:new WeakSet,length_c:0,disconnected:new WeakSet,length_d:0};return e.set(i,f),f}function c(){t||(t=!0,n.observe(document.body,{childList:!0,subtree:!0}))}function s(){!t||e.size||(t=!1,n.disconnect())}function d(){return new Promise(function(i){(requestIdleCallback||requestAnimationFrame)(i)})}async function u(i){e.size>30&&await d();let f=[];if(!(i instanceof Node))return f;for(let a of e.keys())a===i||!(a instanceof Node)||i.contains(a)&&f.push(a);return f}function l(i,f){let a=!1;for(let g of i){if(f&&u(g).then(l),!e.has(g))continue;let w=e.get(g);w.length_c&&(g.dispatchEvent(new Event("dde:connected")),w.connected=new WeakSet,w.length_c=0,w.length_d||e.delete(g),a=!0)}return a}function v(i,f){let a=!1;for(let g of i)f&&u(g).then(v),!(!e.has(g)||!e.get(g).length_d)&&(g.dispatchEvent(new Event("dde:disconnected")),e.delete(g),a=!0);return a}}var p=Symbol.for("observable");function W(e){try{return Reflect.has(e,p)}catch{return!1}}var M=[],h=new WeakMap;function m(e,t){if(typeof e!="function")return Q(e,t);if(W(e))return e;let n=Q(),r=function(){let[o,...c]=h.get(r);if(h.set(r,new Set([o])),M.push(r),n(e()),M.pop(),!c.length)return;let s=h.get(r);for(let d of c)s.has(d)||S(d,r)};return h.set(n[p],r),h.set(r,new Set([n])),r(),n}m.action=function(e,t,...n){let r=e[p],{actions:o}=r;if(!o||!Reflect.has(o,t))throw new Error(`'${e}' has no action with name '${t}'!`);if(o[t].apply(r,n),r.skip)return Reflect.deleteProperty(r,"skip");r.listeners.forEach(c=>c(r.value))};m.on=function e(t,n,r={}){let{signal:o}=r;if(!(o&&o.aborted)){if(Array.isArray(t))return t.forEach(c=>e(c,n,r));U(t,n),o&&o.addEventListener("abort",()=>S(t,n))}};m.symbols={onclear:Symbol.for("Observable.onclear")};m.clear=function(...e){for(let n of e){Reflect.deleteProperty(n,"toJSON");let r=n[p];r.onclear.forEach(o=>o.call(r)),t(n,r),Reflect.deleteProperty(n,p)}function t(n,r){r.listeners.forEach(o=>{if(r.listeners.delete(o),!h.has(o))return;let c=h.get(o);c.delete(n),!(c.size>1)&&(n.clear(...c),h.delete(o))})}};var k="__dde_reactive";m.el=function(e,t){let n=y.mark({type:"reactive"},!1),r=n.end,o=document.createDocumentFragment();o.append(n,r);let{current:c}=b,s=d=>{if(!n.parentNode||!r.parentNode)return S(e,s);b.push(c);let u=t(d);b.pop(),Array.isArray(u)||(u=[u]);let l=n;for(;(l=n.nextSibling)!==r;)l.remove();n.after(...u)};return U(e,s),Y(e,s,n,t),s(e()),o};var R="__dde_attributes";m.attribute=function(e,t=null){let n=m(t),r;return b.host(o=>{if(r=o,O(r,"has",e)?n(O(r,"get",e)):t!==null&&O(r,"set",e,t),o[R]){o[R][e]=n;return}r[R]={[e]:n},_.attributeChanged(function({detail:s}){/*! This maps attributes to observables (`S.attribute`). * Investigate `__dde_attributes` key of the element.*/let[d,u]=s,l=r[R][d];if(l)return l(u)})(r),_.disconnected(function(){/*! This removes all observables mapped to attributes (`S.attribute`). * Investigate `__dde_attributes` key of the element.*/m.clear(...Object.values(r[R]))})(r)}),new Proxy(n,{apply(o,c,s){if(!s.length)return o();let d=s[0];return O(r,"set",e,d)}})};var X={isObservable:W,processReactiveAttribute(e,t,n,r){if(!W(n))return n;let o=c=>r(t,c);return U(n,o),Y(n,o,e,t),n()}};function Y(e,t,...n){let{current:r}=b;r.prevent||r.host(function(o){o[k]||(o[k]=[],_.disconnected(()=>o[k].forEach(([[c,s]])=>S(c,s,c[p]?.host()===o)))(o)),o[k].push([[e,t],...n])})}function Q(e,t){let n=(...r)=>r.length?le(n,...r):de(n);return ue(n,e,t)}var fe=Object.assign(Object.create(null),{stopPropagation(){this.skip=!0}}),q=class extends Error{constructor(){super();let[t,...n]=this.stack.split(` `),r=t.slice(t.indexOf("@"),t.indexOf(".js:")+4);this.stack=n.find(o=>!o.includes(r))}};function ue(e,t,n){let r=[];B(n)!=="[object Object]"&&(n={});let{onclear:o}=m.symbols;n[o]&&(r.push(n[o]),Reflect.deleteProperty(n,o));let{host:c}=b;return Reflect.defineProperty(e,p,{value:{value:t,actions:n,onclear:r,host:c,listeners:new Set,defined:new q},enumerable:!1,writable:!1,configurable:!0}),e.toJSON=()=>e(),Object.setPrototypeOf(e[p],fe),e}function ae(){return M[M.length-1]}function de(e){if(!e[p])return;let{value:t,listeners:n}=e[p],r=ae();return r&&n.add(r),h.has(r)&&h.get(r).add(e),t}function le(e,t,n){if(!e[p])return;let r=e[p];if(!(!n&&r.value===t))return r.value=t,r.listeners.forEach(o=>o(t)),t}function U(e,t){if(e[p])return e[p].listeners.add(t)}function S(e,t,n){let r=e[p];if(!r)return;let o=r.listeners.delete(t);if(n&&!r.listeners.size){if(e.clear(e),!h.has(r))return o;let c=h.get(r);if(!h.has(c))return o;h.get(c).forEach(s=>S(s,c,!0))}return o}T(X);export{m as O,P as assign,Z as assignAttribute,te as chainableAppend,ne as classListDeclarative,y as createElement,Ee as createElementNS,we as dispatchEvent,y as el,Ee as elNS,O as elementAttribute,xe as empty,W as isObservable,m as observable,_ as on,T as registerReactivity,b as scope,_e as simulateSlots}; diff --git a/dist/esm.d.ts b/dist/esm.d.ts index b5a43b8..f9cdf03 100644 --- a/dist/esm.d.ts +++ b/dist/esm.d.ts @@ -1,3 +1,68 @@ +export type Observable= (set?: V)=> V & A; +type Action= (this: { value: V, stopPropagation(): void }, ...a: any[])=> typeof observable._ | void; +//type SymbolObservable= Symbol; +type SymbolOnclear= symbol; +type Actions= Record>; +interface observable{ + _: Symbol + /** + * Simple example: + * ```js + * const hello= S("Hello Observable"); + * ``` + * …simple todo observable: + * ```js + * const todos= S([], { + * add(v){ this.value.push(S(v)); }, + * remove(i){ this.value.splice(i, 1); }, + * [S.symbols.onclear](){ S.clear(...this.value); }, + * }); + * ``` + * …computed observable: + * ```js + * const name= S("Jan"); + * const surname= S("Andrle"); + * const fullname= S(()=> name()+" "+surname()); + * ``` + * @param value Initial observable value. Or function computing value from other observables. + * @param actions Use to define actions on the observable. Such as add item to the array. + * There is also a reserved function `S.symbol.onclear` which is called when the observable is cleared + * by `S.clear`. + * */ + >(value: V, actions?: A): Observable; + /** + * Computations observable. This creates a observable which is computed from other observables. + * */ + (computation: ()=> V): Observable + action>, A extends (S extends Observable ? A : never), N extends keyof A>( + observable: S, + name: N, + ...params: A[N] extends (...args: infer P)=> any ? P : never + ): void; + clear(...observables: Observable[]): void; + on(observable: Observable, onchange: (a: T)=> void, options?: AddEventListenerOptions): void; + symbols: { + //observable: SymbolObservable; + onclear: SymbolOnclear; + } + /** + * Reactive element, which is rendered based on the given observable. + * ```js + * S.el(observable, value=> value ? el("b", "True") : el("i", "False")); + * S.el(listS, list=> list.map(li=> el("li", li))); + * ``` + * */ + el(observable: Observable, el: (v: S)=> Element | Element[] | DocumentFragment): DocumentFragment; + + attribute(name: string, initial?: string): Observable; +} +export const observable: observable; +export const O: observable; +declare global { + type ddeObservable= Observable; + type ddeAction= Action + type ddeActions= Actions +} type CustomElementTagNameMap= { '#text': Text, '#comment': Comment } declare global { interface ddePublicElementTagNameMap{ @@ -19,20 +84,21 @@ type AttrsModified= { /** * Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API). */ - style: string | Partial + style: string | Partial | Observable | Partial<{ [K in keyof CSSStyleDeclaration]: Observable }> /** * Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` for others. */ - classList: Record, + classList: Record>, /** * By default simiral to `className`, but also supports `string[]` * */ - className: string | (string|boolean|undefined)[]; + className: string | (string|boolean|undefined|Observable)[]; /** * Sets `aria-*` simiraly to `dataset` * */ - ariaset: Record, -} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, string> & Record<`.${string}`, any> + ariaset: Record>, +} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, string|Observable> & Record<`.${string}`, any> +type _fromElsInterfaces= Omit; /** * Just element attributtes * @@ -41,17 +107,28 @@ type AttrsModified= { * There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives. * @private */ -type ElementAttributes= Omit & AttrsModified; +type ElementAttributes= Partial<_fromElsInterfaces & { [K in keyof _fromElsInterfaces]: Observable<_fromElsInterfaces[K], any> } & AttrsModified>; export function classListDeclarative(element: El, classList: AttrsModified["classList"]): El -export function assign(element: El, ...attrs_array: Partial>[]): El +export function assign(element: El, ...attrs_array: ElementAttributes[]): El export function assignAttribute>(element: El, attr: ATT, value: ElementAttributes[ATT]): ElementAttributes[ATT] type ExtendedHTMLElementTagNameMap= ddeHTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap -export function el( +export function el< + TAG extends string, + EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : ddeHTMLElement) +>( tag_name: TAG, - attrs?: string | Partial>, - ...addons: ddeElementAddon[] -): ExtendedHTMLElementTagNameMap[TAG] + attrs?: ElementAttributes, + ...addons: ddeElementAddon[] +): EL +export function el< + TAG extends string, + EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : ddeHTMLElement) +>( + tag_name: TAG, + attrs?: string | Observable, + ...addons: ddeElementAddon[] +): EL export function el( tag_name?: "<>", ): ddeDocumentFragment @@ -63,12 +140,7 @@ export function el< attrs?: A | string, ...addons: ddeElementAddon>[] ): ReturnType - -export function el( - tag_name: string, - attrs?: string | Record, - ...addons: ddeElementAddon[] -): ddeHTMLElement +export { el as createElement } export function elNS( namespace: "http://www.w3.org/2000/svg" @@ -91,6 +163,7 @@ export function elNS( attrs?: string | Record, ...addons: ddeElementAddon[] )=> SupportedElement +export { elNS as createElementNS } export function chainableAppend(el: EL): EL; export function simulateSlots(el: EL): EL @@ -250,71 +323,6 @@ declare global{ "ul": ddeHTMLUListElement; "video": ddeHTMLVideoElement; } - interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend; } - interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend; } - interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend; } - interface ddeHTMLBaseElement extends HTMLBaseElement{ append: ddeAppend; } - interface ddeHTMLQuoteElement extends HTMLQuoteElement{ append: ddeAppend; } - interface ddeHTMLBodyElement extends HTMLBodyElement{ append: ddeAppend; } - interface ddeHTMLBRElement extends HTMLBRElement{ append: ddeAppend; } - interface ddeHTMLButtonElement extends HTMLButtonElement{ append: ddeAppend; } - interface ddeHTMLCanvasElement extends HTMLCanvasElement{ append: ddeAppend; } - interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement{ append: ddeAppend; } - interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } - interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } - interface ddeHTMLDataElement extends HTMLDataElement{ append: ddeAppend; } - interface ddeHTMLDataListElement extends HTMLDataListElement{ append: ddeAppend; } - interface ddeHTMLModElement extends HTMLModElement{ append: ddeAppend; } - interface ddeHTMLDetailsElement extends HTMLDetailsElement{ append: ddeAppend; } - interface ddeHTMLDialogElement extends HTMLDialogElement{ append: ddeAppend; } - interface ddeHTMLDivElement extends HTMLDivElement{ append: ddeAppend; } - interface ddeHTMLDListElement extends HTMLDListElement{ append: ddeAppend; } - interface ddeHTMLEmbedElement extends HTMLEmbedElement{ append: ddeAppend; } - interface ddeHTMLFieldSetElement extends HTMLFieldSetElement{ append: ddeAppend; } - interface ddeHTMLFormElement extends HTMLFormElement{ append: ddeAppend; } - interface ddeHTMLHeadingElement extends HTMLHeadingElement{ append: ddeAppend; } - interface ddeHTMLHeadElement extends HTMLHeadElement{ append: ddeAppend; } - interface ddeHTMLHRElement extends HTMLHRElement{ append: ddeAppend; } - interface ddeHTMLHtmlElement extends HTMLHtmlElement{ append: ddeAppend; } - interface ddeHTMLIFrameElement extends HTMLIFrameElement{ append: ddeAppend; } - interface ddeHTMLImageElement extends HTMLImageElement{ append: ddeAppend; } - interface ddeHTMLInputElement extends HTMLInputElement{ append: ddeAppend; } - interface ddeHTMLLabelElement extends HTMLLabelElement{ append: ddeAppend; } - interface ddeHTMLLegendElement extends HTMLLegendElement{ append: ddeAppend; } - interface ddeHTMLLIElement extends HTMLLIElement{ append: ddeAppend; } - interface ddeHTMLLinkElement extends HTMLLinkElement{ append: ddeAppend; } - interface ddeHTMLMapElement extends HTMLMapElement{ append: ddeAppend; } - interface ddeHTMLMenuElement extends HTMLMenuElement{ append: ddeAppend; } - interface ddeHTMLMetaElement extends HTMLMetaElement{ append: ddeAppend; } - interface ddeHTMLMeterElement extends HTMLMeterElement{ append: ddeAppend; } - interface ddeHTMLObjectElement extends HTMLObjectElement{ append: ddeAppend; } - interface ddeHTMLOListElement extends HTMLOListElement{ append: ddeAppend; } - interface ddeHTMLOptGroupElement extends HTMLOptGroupElement{ append: ddeAppend; } - interface ddeHTMLOptionElement extends HTMLOptionElement{ append: ddeAppend; } - interface ddeHTMLOutputElement extends HTMLOutputElement{ append: ddeAppend; } - interface ddeHTMLParagraphElement extends HTMLParagraphElement{ append: ddeAppend; } - interface ddeHTMLPictureElement extends HTMLPictureElement{ append: ddeAppend; } - interface ddeHTMLPreElement extends HTMLPreElement{ append: ddeAppend; } - interface ddeHTMLProgressElement extends HTMLProgressElement{ append: ddeAppend; } - interface ddeHTMLScriptElement extends HTMLScriptElement{ append: ddeAppend; } - interface ddeHTMLSelectElement extends HTMLSelectElement{ append: ddeAppend; } - interface ddeHTMLSlotElement extends HTMLSlotElement{ append: ddeAppend; } - interface ddeHTMLSourceElement extends HTMLSourceElement{ append: ddeAppend; } - interface ddeHTMLSpanElement extends HTMLSpanElement{ append: ddeAppend; } - interface ddeHTMLStyleElement extends HTMLStyleElement{ append: ddeAppend; } - interface ddeHTMLTableElement extends HTMLTableElement{ append: ddeAppend; } - interface ddeHTMLTableSectionElement extends HTMLTableSectionElement{ append: ddeAppend; } - interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } - interface ddeHTMLTemplateElement extends HTMLTemplateElement{ append: ddeAppend; } - interface ddeHTMLTextAreaElement extends HTMLTextAreaElement{ append: ddeAppend; } - interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } - interface ddeHTMLTimeElement extends HTMLTimeElement{ append: ddeAppend; } - interface ddeHTMLTitleElement extends HTMLTitleElement{ append: ddeAppend; } - interface ddeHTMLTableRowElement extends HTMLTableRowElement{ append: ddeAppend; } - interface ddeHTMLTrackElement extends HTMLTrackElement{ append: ddeAppend; } - interface ddeHTMLUListElement extends HTMLUListElement{ append: ddeAppend; } - interface ddeHTMLVideoElement extends HTMLVideoElement{ append: ddeAppend; } - interface ddeSVGElementTagNameMap { "a": ddeSVGAElement; "animate": ddeSVGAnimateElement; @@ -380,67 +388,132 @@ declare global{ "use": ddeSVGUseElement; "view": ddeSVGViewElement; } - interface ddeSVGAElement extends SVGAElement{ append: ddeAppend; } - interface ddeSVGAnimateElement extends SVGAnimateElement{ append: ddeAppend; } - interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement{ append: ddeAppend; } - interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement{ append: ddeAppend; } - interface ddeSVGCircleElement extends SVGCircleElement{ append: ddeAppend; } - interface ddeSVGClipPathElement extends SVGClipPathElement{ append: ddeAppend; } - interface ddeSVGDefsElement extends SVGDefsElement{ append: ddeAppend; } - interface ddeSVGDescElement extends SVGDescElement{ append: ddeAppend; } - interface ddeSVGEllipseElement extends SVGEllipseElement{ append: ddeAppend; } - interface ddeSVGFEBlendElement extends SVGFEBlendElement{ append: ddeAppend; } - interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement{ append: ddeAppend; } - interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement{ append: ddeAppend; } - interface ddeSVGFECompositeElement extends SVGFECompositeElement{ append: ddeAppend; } - interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement{ append: ddeAppend; } - interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement{ append: ddeAppend; } - interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement{ append: ddeAppend; } - interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement{ append: ddeAppend; } - interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement{ append: ddeAppend; } - interface ddeSVGFEFloodElement extends SVGFEFloodElement{ append: ddeAppend; } - interface ddeSVGFEFuncAElement extends SVGFEFuncAElement{ append: ddeAppend; } - interface ddeSVGFEFuncBElement extends SVGFEFuncBElement{ append: ddeAppend; } - interface ddeSVGFEFuncGElement extends SVGFEFuncGElement{ append: ddeAppend; } - interface ddeSVGFEFuncRElement extends SVGFEFuncRElement{ append: ddeAppend; } - interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement{ append: ddeAppend; } - interface ddeSVGFEImageElement extends SVGFEImageElement{ append: ddeAppend; } - interface ddeSVGFEMergeElement extends SVGFEMergeElement{ append: ddeAppend; } - interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement{ append: ddeAppend; } - interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement{ append: ddeAppend; } - interface ddeSVGFEOffsetElement extends SVGFEOffsetElement{ append: ddeAppend; } - interface ddeSVGFEPointLightElement extends SVGFEPointLightElement{ append: ddeAppend; } - interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement{ append: ddeAppend; } - interface ddeSVGFESpotLightElement extends SVGFESpotLightElement{ append: ddeAppend; } - interface ddeSVGFETileElement extends SVGFETileElement{ append: ddeAppend; } - interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement{ append: ddeAppend; } - interface ddeSVGFilterElement extends SVGFilterElement{ append: ddeAppend; } - interface ddeSVGForeignObjectElement extends SVGForeignObjectElement{ append: ddeAppend; } - interface ddeSVGGElement extends SVGGElement{ append: ddeAppend; } - interface ddeSVGImageElement extends SVGImageElement{ append: ddeAppend; } - interface ddeSVGLineElement extends SVGLineElement{ append: ddeAppend; } - interface ddeSVGLinearGradientElement extends SVGLinearGradientElement{ append: ddeAppend; } - interface ddeSVGMarkerElement extends SVGMarkerElement{ append: ddeAppend; } - interface ddeSVGMaskElement extends SVGMaskElement{ append: ddeAppend; } - interface ddeSVGMetadataElement extends SVGMetadataElement{ append: ddeAppend; } - interface ddeSVGMPathElement extends SVGMPathElement{ append: ddeAppend; } - interface ddeSVGPathElement extends SVGPathElement{ append: ddeAppend; } - interface ddeSVGPatternElement extends SVGPatternElement{ append: ddeAppend; } - interface ddeSVGPolygonElement extends SVGPolygonElement{ append: ddeAppend; } - interface ddeSVGPolylineElement extends SVGPolylineElement{ append: ddeAppend; } - interface ddeSVGRadialGradientElement extends SVGRadialGradientElement{ append: ddeAppend; } - interface ddeSVGRectElement extends SVGRectElement{ append: ddeAppend; } - interface ddeSVGScriptElement extends SVGScriptElement{ append: ddeAppend; } - interface ddeSVGSetElement extends SVGSetElement{ append: ddeAppend; } - interface ddeSVGStopElement extends SVGStopElement{ append: ddeAppend; } - interface ddeSVGStyleElement extends SVGStyleElement{ append: ddeAppend; } - interface ddeSVGSVGElement extends SVGSVGElement{ append: ddeAppend; } - interface ddeSVGSwitchElement extends SVGSwitchElement{ append: ddeAppend; } - interface ddeSVGSymbolElement extends SVGSymbolElement{ append: ddeAppend; } - interface ddeSVGTextElement extends SVGTextElement{ append: ddeAppend; } - interface ddeSVGTextPathElement extends SVGTextPathElement{ append: ddeAppend; } - interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend; } - interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend; } - interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend; } - interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend; } -} \ No newline at end of file +} + +interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend; } +interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend; } +interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend; } +interface ddeHTMLBaseElement extends HTMLBaseElement{ append: ddeAppend; } +interface ddeHTMLQuoteElement extends HTMLQuoteElement{ append: ddeAppend; } +interface ddeHTMLBodyElement extends HTMLBodyElement{ append: ddeAppend; } +interface ddeHTMLBRElement extends HTMLBRElement{ append: ddeAppend; } +interface ddeHTMLButtonElement extends HTMLButtonElement{ append: ddeAppend; } +interface ddeHTMLCanvasElement extends HTMLCanvasElement{ append: ddeAppend; } +interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement{ append: ddeAppend; } +interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } +interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } +interface ddeHTMLDataElement extends HTMLDataElement{ append: ddeAppend; } +interface ddeHTMLDataListElement extends HTMLDataListElement{ append: ddeAppend; } +interface ddeHTMLModElement extends HTMLModElement{ append: ddeAppend; } +interface ddeHTMLDetailsElement extends HTMLDetailsElement{ append: ddeAppend; } +interface ddeHTMLDialogElement extends HTMLDialogElement{ append: ddeAppend; } +interface ddeHTMLDivElement extends HTMLDivElement{ append: ddeAppend; } +interface ddeHTMLDListElement extends HTMLDListElement{ append: ddeAppend; } +interface ddeHTMLEmbedElement extends HTMLEmbedElement{ append: ddeAppend; } +interface ddeHTMLFieldSetElement extends HTMLFieldSetElement{ append: ddeAppend; } +interface ddeHTMLFormElement extends HTMLFormElement{ append: ddeAppend; } +interface ddeHTMLHeadingElement extends HTMLHeadingElement{ append: ddeAppend; } +interface ddeHTMLHeadElement extends HTMLHeadElement{ append: ddeAppend; } +interface ddeHTMLHRElement extends HTMLHRElement{ append: ddeAppend; } +interface ddeHTMLHtmlElement extends HTMLHtmlElement{ append: ddeAppend; } +interface ddeHTMLIFrameElement extends HTMLIFrameElement{ append: ddeAppend; } +interface ddeHTMLImageElement extends HTMLImageElement{ append: ddeAppend; } +interface ddeHTMLInputElement extends HTMLInputElement{ append: ddeAppend; } +interface ddeHTMLLabelElement extends HTMLLabelElement{ append: ddeAppend; } +interface ddeHTMLLegendElement extends HTMLLegendElement{ append: ddeAppend; } +interface ddeHTMLLIElement extends HTMLLIElement{ append: ddeAppend; } +interface ddeHTMLLinkElement extends HTMLLinkElement{ append: ddeAppend; } +interface ddeHTMLMapElement extends HTMLMapElement{ append: ddeAppend; } +interface ddeHTMLMenuElement extends HTMLMenuElement{ append: ddeAppend; } +interface ddeHTMLMetaElement extends HTMLMetaElement{ append: ddeAppend; } +interface ddeHTMLMeterElement extends HTMLMeterElement{ append: ddeAppend; } +interface ddeHTMLObjectElement extends HTMLObjectElement{ append: ddeAppend; } +interface ddeHTMLOListElement extends HTMLOListElement{ append: ddeAppend; } +interface ddeHTMLOptGroupElement extends HTMLOptGroupElement{ append: ddeAppend; } +interface ddeHTMLOptionElement extends HTMLOptionElement{ append: ddeAppend; } +interface ddeHTMLOutputElement extends HTMLOutputElement{ append: ddeAppend; } +interface ddeHTMLParagraphElement extends HTMLParagraphElement{ append: ddeAppend; } +interface ddeHTMLPictureElement extends HTMLPictureElement{ append: ddeAppend; } +interface ddeHTMLPreElement extends HTMLPreElement{ append: ddeAppend; } +interface ddeHTMLProgressElement extends HTMLProgressElement{ append: ddeAppend; } +interface ddeHTMLScriptElement extends HTMLScriptElement{ append: ddeAppend; } +interface ddeHTMLSelectElement extends HTMLSelectElement{ append: ddeAppend; } +interface ddeHTMLSlotElement extends HTMLSlotElement{ append: ddeAppend; } +interface ddeHTMLSourceElement extends HTMLSourceElement{ append: ddeAppend; } +interface ddeHTMLSpanElement extends HTMLSpanElement{ append: ddeAppend; } +interface ddeHTMLStyleElement extends HTMLStyleElement{ append: ddeAppend; } +interface ddeHTMLTableElement extends HTMLTableElement{ append: ddeAppend; } +interface ddeHTMLTableSectionElement extends HTMLTableSectionElement{ append: ddeAppend; } +interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } +interface ddeHTMLTemplateElement extends HTMLTemplateElement{ append: ddeAppend; } +interface ddeHTMLTextAreaElement extends HTMLTextAreaElement{ append: ddeAppend; } +interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } +interface ddeHTMLTimeElement extends HTMLTimeElement{ append: ddeAppend; } +interface ddeHTMLTitleElement extends HTMLTitleElement{ append: ddeAppend; } +interface ddeHTMLTableRowElement extends HTMLTableRowElement{ append: ddeAppend; } +interface ddeHTMLTrackElement extends HTMLTrackElement{ append: ddeAppend; } +interface ddeHTMLUListElement extends HTMLUListElement{ append: ddeAppend; } +interface ddeHTMLVideoElement extends HTMLVideoElement{ append: ddeAppend; } +interface ddeSVGAElement extends SVGAElement{ append: ddeAppend; } +interface ddeSVGAnimateElement extends SVGAnimateElement{ append: ddeAppend; } +interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement{ append: ddeAppend; } +interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement{ append: ddeAppend; } +interface ddeSVGCircleElement extends SVGCircleElement{ append: ddeAppend; } +interface ddeSVGClipPathElement extends SVGClipPathElement{ append: ddeAppend; } +interface ddeSVGDefsElement extends SVGDefsElement{ append: ddeAppend; } +interface ddeSVGDescElement extends SVGDescElement{ append: ddeAppend; } +interface ddeSVGEllipseElement extends SVGEllipseElement{ append: ddeAppend; } +interface ddeSVGFEBlendElement extends SVGFEBlendElement{ append: ddeAppend; } +interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement{ append: ddeAppend; } +interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement{ append: ddeAppend; } +interface ddeSVGFECompositeElement extends SVGFECompositeElement{ append: ddeAppend; } +interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement{ append: ddeAppend; } +interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement{ append: ddeAppend; } +interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement{ append: ddeAppend; } +interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement{ append: ddeAppend; } +interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement{ append: ddeAppend; } +interface ddeSVGFEFloodElement extends SVGFEFloodElement{ append: ddeAppend; } +interface ddeSVGFEFuncAElement extends SVGFEFuncAElement{ append: ddeAppend; } +interface ddeSVGFEFuncBElement extends SVGFEFuncBElement{ append: ddeAppend; } +interface ddeSVGFEFuncGElement extends SVGFEFuncGElement{ append: ddeAppend; } +interface ddeSVGFEFuncRElement extends SVGFEFuncRElement{ append: ddeAppend; } +interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement{ append: ddeAppend; } +interface ddeSVGFEImageElement extends SVGFEImageElement{ append: ddeAppend; } +interface ddeSVGFEMergeElement extends SVGFEMergeElement{ append: ddeAppend; } +interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement{ append: ddeAppend; } +interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement{ append: ddeAppend; } +interface ddeSVGFEOffsetElement extends SVGFEOffsetElement{ append: ddeAppend; } +interface ddeSVGFEPointLightElement extends SVGFEPointLightElement{ append: ddeAppend; } +interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement{ append: ddeAppend; } +interface ddeSVGFESpotLightElement extends SVGFESpotLightElement{ append: ddeAppend; } +interface ddeSVGFETileElement extends SVGFETileElement{ append: ddeAppend; } +interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement{ append: ddeAppend; } +interface ddeSVGFilterElement extends SVGFilterElement{ append: ddeAppend; } +interface ddeSVGForeignObjectElement extends SVGForeignObjectElement{ append: ddeAppend; } +interface ddeSVGGElement extends SVGGElement{ append: ddeAppend; } +interface ddeSVGImageElement extends SVGImageElement{ append: ddeAppend; } +interface ddeSVGLineElement extends SVGLineElement{ append: ddeAppend; } +interface ddeSVGLinearGradientElement extends SVGLinearGradientElement{ append: ddeAppend; } +interface ddeSVGMarkerElement extends SVGMarkerElement{ append: ddeAppend; } +interface ddeSVGMaskElement extends SVGMaskElement{ append: ddeAppend; } +interface ddeSVGMetadataElement extends SVGMetadataElement{ append: ddeAppend; } +interface ddeSVGMPathElement extends SVGMPathElement{ append: ddeAppend; } +interface ddeSVGPathElement extends SVGPathElement{ append: ddeAppend; } +interface ddeSVGPatternElement extends SVGPatternElement{ append: ddeAppend; } +interface ddeSVGPolygonElement extends SVGPolygonElement{ append: ddeAppend; } +interface ddeSVGPolylineElement extends SVGPolylineElement{ append: ddeAppend; } +interface ddeSVGRadialGradientElement extends SVGRadialGradientElement{ append: ddeAppend; } +interface ddeSVGRectElement extends SVGRectElement{ append: ddeAppend; } +interface ddeSVGScriptElement extends SVGScriptElement{ append: ddeAppend; } +interface ddeSVGSetElement extends SVGSetElement{ append: ddeAppend; } +interface ddeSVGStopElement extends SVGStopElement{ append: ddeAppend; } +interface ddeSVGStyleElement extends SVGStyleElement{ append: ddeAppend; } +interface ddeSVGSVGElement extends SVGSVGElement{ append: ddeAppend; } +interface ddeSVGSwitchElement extends SVGSwitchElement{ append: ddeAppend; } +interface ddeSVGSymbolElement extends SVGSymbolElement{ append: ddeAppend; } +interface ddeSVGTextElement extends SVGTextElement{ append: ddeAppend; } +interface ddeSVGTextPathElement extends SVGTextPathElement{ append: ddeAppend; } +interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend; } +interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend; } +interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend; } +interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend; } \ No newline at end of file diff --git a/docs/global.css b/docs/global.css index 6858d3c..ac7571f 100644 --- a/docs/global.css +++ b/docs/global.css @@ -18,7 +18,7 @@ body { @media (min-width:768px) { body{ grid-template-rows: auto auto; - grid-template-columns: calc(var(--body-max-width) / 3) auto; + grid-template-columns: calc(10 * var(--body-max-width) / 27) auto; grid-template-areas: "header header" "sidebar content" diff --git a/docs/p02-elements.html b/docs/p02-elements.html index 4662d87..5f8e9ea 100644 --- a/docs/p02-elements.html +++ b/docs/p02-elements.html @@ -1,7 +1,11 @@ -`deka-dom-el` — Elements

`deka-dom-el` — Elements

Basic concepts of elements modifications and creations.

Native JavaScript DOM elements creations

Let’s go through all patterns we would like to use and what needs to be improved for better experience.

// when NPM -import { assign, el, elNS } from "deka-dom-el"; -// https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js - +`deka-dom-el` — Elements

`deka-dom-el` — Elements

Basic concepts of elements modifications and creations.

Native JavaScript DOM elements creations

Let’s go through all patterns we would like to use and what needs to be improved for better experience.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js +import { + assign, + el, createElement, + elNS, createElementNS +} from "deka-dom-el"; +el===createElement +elNS===createElementNS // “internal” utils import { assignAttribute, @@ -140,4 +144,4 @@ document.body.append( console.log( document.body.innerHTML.includes("<svg></svg><math></math>") ) -

# Mnemonic

  • assign(<element>, ...<idl-objects>): <element> — assign properties to the element
  • el(<tag-name>, <primitive>)[.append(...)]: <element-from-tag-name> — simple element containing only text
  • el(<tag-name>, <idl-object>)[.append(...)]: <element-from-tag-name> — element with more properties
  • el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function> — using component represented by function
  • el(<...>, <...>, ...<addons>) — see following page
  • elNS(<namespace>)(<as-el-see-above>)[.append(...)]: <element-based-on-arguments> — typically SVG elements
\ No newline at end of file +

# Mnemonic

  • assign(<element>, ...<idl-objects>): <element> — assign properties to the element
  • el(<tag-name>, <primitive>)[.append(...)]: <element-from-tag-name> — simple element containing only text
  • el(<tag-name>, <idl-object>)[.append(...)]: <element-from-tag-name> — element with more properties
  • el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function> — using component represented by function
  • el(<...>, <...>, ...<addons>) — see following page
  • elNS(<namespace>)(<as-el-see-above>)[.append(...)]: <element-based-on-arguments> — typically SVG elements
\ No newline at end of file diff --git a/docs/p03-events.html b/docs/p03-events.html index 8032733..eeeb376 100644 --- a/docs/p03-events.html +++ b/docs/p03-events.html @@ -1,10 +1,7 @@ -`deka-dom-el` — Events and Addons

`deka-dom-el` — Events and Addons

Using not only events in UI declaratively.

Listenning to the native DOM events and other Addons

We quickly introduce helper to listening to the native DOM events. And library syntax/pattern so-called Addon to incorporate not only this in UI templates declaratively.

// when NPM +`deka-dom-el` — Events and Addons

`deka-dom-el` — Events and Addons

Using not only events in UI declaratively.

Listenning to the native DOM events and other Addons

We quickly introduce helper to listening to the native DOM events. And library syntax/pattern so-called Addon to incorporate not only this in UI templates declaratively.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js import { on, dispatchEvent } from "deka-dom-el"; -// https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js -/** - * @type {ddeElementAddon} - * */ +/** @type {ddeElementAddon} */

# Events and listenners

In JavaScript you can listen to the native DOM events of the given element by using element.addEventListener(type, listener, options). The library provides an alternative (on) accepting the differen order of the arguments:

import { el, on } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; const log= mark=> console.log.bind(console, mark); @@ -94,4 +91,4 @@ function dde(){ function ddeOptions(){ dispatchEvent("test", { bubbles: true })(this, "hi"); } -

# Mnemonic

  • on(<event>, <listener>[, <options>])(<element>) — just <element>.addEventListener(<event>, <listener>[, <options>])
  • on.<live-cycle>(<event>, <listener>[, <options>])(<element>) — corresponds to custom elemnets callbacks <live-cycle>Callback(...){...}. To connect to custom element see following page, else it is simulated by MutationObserver.
  • dispatchEvent(<event>[, <options>])(element) — just <element>.dispatchEvent(new Event(<event>[, <options>]))
  • dispatchEvent(<event>[, <options>])(element, detail) — just <element>.dispatchEvent(new CustomEvent(<event>, { detail, ...<options> }))
\ No newline at end of file +

# Mnemonic

  • on(<event>, <listener>[, <options>])(<element>) — just <element>.addEventListener(<event>, <listener>[, <options>])
  • on.<live-cycle>(<event>, <listener>[, <options>])(<element>) — corresponds to custom elemnets callbacks <live-cycle>Callback(...){...}. To connect to custom element see following page, else it is simulated by MutationObserver.
  • dispatchEvent(<event>[, <options>])(element) — just <element>.dispatchEvent(new Event(<event>[, <options>]))
  • dispatchEvent(<event>[, <options>])(element, detail) — just <element>.dispatchEvent(new CustomEvent(<event>, { detail, ...<options> }))
\ No newline at end of file diff --git a/docs/p04-observables.html b/docs/p04-observables.html index 7635786..ce28451 100644 --- a/docs/p04-observables.html +++ b/docs/p04-observables.html @@ -1,22 +1,22 @@ -`deka-dom-el` — Observables and reactivity

`deka-dom-el` — Observables and reactivity

Handling reactivity in UI via observables.

Using observables to manage reactivity

How a program responds to variable data or user interactions is one of the fundamental problems of programming. If we desire to solve the issue in a declarative manner, observables may be a viable approach.

// when NPM -import { O } from "deka-dom-el/observables"; -// https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js - -/** - * @type {ddeObservable} - * */ -/** - * @type {ddeActions} - * */ +`deka-dom-el` — Observables and reactivity

`deka-dom-el` — Observables and reactivity

Handling reactivity in UI via observables.

Using observables to manage reactivity

How a program responds to variable data or user interactions is one of the fundamental problems of programming. If we desire to solve the issue in a declarative manner, observables may be a viable approach.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js +import { O, observable } from "deka-dom-el/observables"; +O===observable +/** @type {ddeObservable} */ +/** @type {ddeAction} */ +/** @type {ddeActions} */

# Introducing observables

Using observables, we split program logic into the three parts. Firstly (α), we create a variable (constant) representing reactive value. Somewhere later, we can register (β) a logic reacting to the observable value changes. Similarly, in a remaining part (γ), we can update the observable value.

import { O } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; // α — `observable` represents a reactive value const observable= O(0); // β — just reacts on observable changes O.on(observable, console.log); // γ — just updates the value -observable(observable()+1); -setInterval(()=> observable(observable()+1), 5000); -

All this is just an example of Event-driven programming and Publish–subscribe pattern (compare for example with fpubsub library). All three parts can be in some manner independent and still connected to the same reactive entity.

Observables are implemented in the library as functions. To see current value of observable, just call it without any arguments console.log(observable()). To update the observable value, pass any argument observable('a new value'). For listenning the observable value changes, use O.on(observable, console.log).

Similarly to the on function to register DOM events listener. You can use AbortController/AbortSignal to off/stop listenning. For representing “live” piece of code computation pattern:

import { O } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; +const update= ()=> observable(observable()+1); + +update(); +const interval= 5*1000; +setTimeout(clearInterval, 10*interval, + setInterval(update, interval)); +

All this is just an example of Event-driven programming and Publish–subscribe pattern (compare for example with fpubsub library). All three parts can be in some manner independent and still connected to the same reactive entity.

Observables are implemented in the library as functions. To see current value of observable, just call it without any arguments console.log(observable()). To update the observable value, pass any argument observable('a new value'). For listenning the observable value changes, use O.on(observable, console.log).

Similarly to the on function to register DOM events listener. You can use AbortController/AbortSignal to off/stop listenning. In example, you also found the way for representing “live” piece of code computation pattern (derived observable):

import { O } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; const observable= O(0); // computation pattern const double= O(()=> 2*observable()); @@ -26,10 +26,125 @@ O.on(observable, v=> console.log("observable", v), { signal: ac.signal }); O.on(double, v=> console.log("double", v), { signal: ac.signal }); observable(observable()+1); -const interval= 5000; +const interval= 5 * 1000; const id= setInterval(()=> observable(observable()+1), interval); ac.signal.addEventListener("abort", ()=> setTimeout(()=> clearInterval(id), 2*interval)); setTimeout(()=> ac.abort(), 3*interval) -

# Mnemonic

  • O(<value>) — observable: reactive value
  • O(()=> <computation>) — observable: reactive value dependent on calculation using other observables
  • O.on(<observable>, <listener>[, <options>]) — listen to the observable value changes
  • O.clear(...<observables>) — off and clear observables
  • O(<value>, <actions>) — observable: pattern to create complex reactive objects/arrays
  • O.action(<observable>, <action-name>, ...<action-arguments>) — invoke an action for given observable
\ No newline at end of file +

# Observables and actions

O(/* primitive */) allows you to declare simple reactive variables, typically around immutable primitive types. However, it may also be necessary to use reactive arrays, objects, or other complex reactive structures.

import { O } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; +const observable= O(0, { + increaseOnlyOdd(add){ + console.info(add); + if(add%2 === 0) return this.stopPropagation(); + this.value+= add; + } +}); +O.on(observable, console.log); +const oninterval= ()=> + O.action(observable, "increaseOnlyOdd", Math.floor(Math.random()*100)); + +const interval= 5*1000; +setTimeout( + clearInterval, + 10*interval, + setInterval(oninterval, interval) +); +

…but typical user-case is object/array (maps, sets and other mutable objects):

import { O } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; +const todos= O([], { + push(item){ + this.value.push(O(item)); + }, + pop(){ + const removed= this.value.pop(); + if(removed) O.clear(removed); + }, + [O.symbols.onclear](){ // this covers `O.clear(todos)` + O.clear(...this.value); + } +}); + +import { el, on } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; +/** @type {ddeElementAddon<HTMLFormElement>} */ +const onsubmit= on("submit", function(event){ + event.preventDefault(); + const data= new FormData(this); + switch (data.get("op")){ + case "A"/*dd*/: + O.action(todos, "push", data.get("todo")); + break; + case "E"/*dit*/: { + const last= todos().at(-1); + if(!last) break; + last(data.get("todo")); + break; + } + case "R"/*emove*/: + O.action(todos, "pop"); + break; + } +}); +document.body.append( + el("ul").append( + O.el(todos, todos=> + todos.map(textContent=> el("li", textContent))) + ), + el("form", null, onsubmit).append( + el("input", { type: "text", name: "todo", placeholder: "Todo’s text" }), + el(radio, { textContent: "Add", checked: true }), + el(radio, { textContent: "Edit last" }), + el(radio, { textContent: "Remove" }), + el("button", "Submit") + ) +); +document.head.append( + el("style", "form{ display: flex; flex-flow: column nowrap; }") +); +function radio({ textContent, checked= false }){ + return el("label").append( + el("input", { type: "radio", name: "op", value: textContent[0], checked }), + " ",textContent + ) +} +

In some way, you can compare it with useReducer hook from React. So, the O(<data>, <actions>) pattern creates a store “machine”. We can then invoke (dispatch) registered action by calling O.action(<observable>, <name>, ...<args>) after the action call the observable calls all its listeners. This can be stopped by calling this.stopPropagation() in the method representing the given action. As it can be seen in examples, the “store” value is available also in the function for given action (this.value).

# Reactive DOM attributes and elements

There are on basic level two distinc situation to mirror dynamic value into the DOM/UI

  1. to change some attribute(s) of existing element(s)
  2. to generate elements itself dynamically – this covers conditions and loops
import { O } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; +const count= O(0); + +import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; +document.body.append( + el("p", O(()=> "Currently: "+count())), + el("p", { classList: { red: O(()=> count()%2) }, dataset: { count }, textContent: "Attributes example" }) +); +document.head.append( + el("style", ".red { color: red; }") +); + +const interval= 5 * 1000; +setTimeout(clearInterval, 10*interval, + setInterval(()=> count(count()+1), interval)); +

To derived attribute based on value of observable variable just use the observable as a value of the attribute (assign(element, { attribute: O('value') })). assign/el provides ways to glue reactive attributes/classes more granularly into the DOM. Just use dedicated build-in attributes dataset, ariaset and classList.

For computation, you can use the derived observable (see above) like assign(element, { textContent: O(()=> 'Hello '+WorldObservable()) }).

To represent part of the template filled dynamically based on the observable value use O.el(observable, DOMgenerator). This was already used in the todo example above or see:

import { O } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; +const count= O(0, { + add(){ this.value= this.value + Math.round(Math.random()*10); } +}); +const numbers= O([ count() ], { + push(next){ this.value.push(next); } +}); + +import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js"; +document.body.append( + O.el(count, count=> count%2 + ? el("p", "Last number is odd.") + : el() + ), + el("p", "Lucky numbers:"), + el("ul").append( + O.el(numbers, numbers=> numbers.toReversed() + .map(n=> el("li", n))) + ) +); + +const interval= 5*1000; +setTimeout(clearInterval, 10*interval, setInterval(function(){ + O.action(count, "add"); + O.action(numbers, "push", count()); +}, interval)); +

# Mnemonic

  • O(<value>) — observable: reactive value
  • O(()=> <computation>) — observable: reactive value dependent on calculation using other observables
  • O.on(<observable>, <listener>[, <options>]) — listen to the observable value changes
  • O.clear(...<observables>) — off and clear observables
  • O(<value>, <actions>) — observable: pattern to create complex reactive objects/arrays
  • O.action(<observable>, <action-name>, ...<action-arguments>) — invoke an action for given observable
  • O.el(<observable>, <function-returning-dom>) — render partial dom structure (template) based on the current observable value
\ No newline at end of file diff --git a/docs_src/components/examples/elements/intro.js b/docs_src/components/examples/elements/intro.js index 027f37e..d41d9cf 100644 --- a/docs_src/components/examples/elements/intro.js +++ b/docs_src/components/examples/elements/intro.js @@ -1,7 +1,11 @@ -// when NPM -import { assign, el, elNS } from "deka-dom-el"; -// https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js - +// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js +import { + assign, + el, createElement, + elNS, createElementNS +} from "deka-dom-el"; +el===createElement +elNS===createElementNS // “internal” utils import { assignAttribute, diff --git a/docs_src/components/examples/events/intro.js b/docs_src/components/examples/events/intro.js index 199ecbb..7ecc352 100644 --- a/docs_src/components/examples/events/intro.js +++ b/docs_src/components/examples/events/intro.js @@ -1,7 +1,4 @@ -// when NPM +// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js import { on, dispatchEvent } from "deka-dom-el"; -// https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js -/** - * @type {ddeElementAddon} - * */ +/** @type {ddeElementAddon} */ diff --git a/docs_src/components/examples/observables/actions-demo.js b/docs_src/components/examples/observables/actions-demo.js new file mode 100644 index 0000000..97b1904 --- /dev/null +++ b/docs_src/components/examples/observables/actions-demo.js @@ -0,0 +1,18 @@ +import { O } from "deka-dom-el/observables"; +const observable= O(0, { + increaseOnlyOdd(add){ + console.info(add); + if(add%2 === 0) return this.stopPropagation(); + this.value+= add; + } +}); +O.on(observable, console.log); +const oninterval= ()=> + O.action(observable, "increaseOnlyOdd", Math.floor(Math.random()*100)); + +const interval= 5*1000; +setTimeout( + clearInterval, + 10*interval, + setInterval(oninterval, interval) +); diff --git a/docs_src/components/examples/observables/actions-todos.js b/docs_src/components/examples/observables/actions-todos.js new file mode 100644 index 0000000..c0a64d9 --- /dev/null +++ b/docs_src/components/examples/observables/actions-todos.js @@ -0,0 +1,56 @@ +import { O } from "deka-dom-el/observables"; +const todos= O([], { + push(item){ + this.value.push(O(item)); + }, + pop(){ + const removed= this.value.pop(); + if(removed) O.clear(removed); + }, + [O.symbols.onclear](){ // this covers `O.clear(todos)` + O.clear(...this.value); + } +}); + +import { el, on } from "deka-dom-el"; +/** @type {ddeElementAddon} */ +const onsubmit= on("submit", function(event){ + event.preventDefault(); + const data= new FormData(this); + switch (data.get("op")){ + case "A"/*dd*/: + O.action(todos, "push", data.get("todo")); + break; + case "E"/*dit*/: { + const last= todos().at(-1); + if(!last) break; + last(data.get("todo")); + break; + } + case "R"/*emove*/: + O.action(todos, "pop"); + break; + } +}); +document.body.append( + el("ul").append( + O.el(todos, todos=> + todos.map(textContent=> el("li", textContent))) + ), + el("form", null, onsubmit).append( + el("input", { type: "text", name: "todo", placeholder: "Todo’s text" }), + el(radio, { textContent: "Add", checked: true }), + el(radio, { textContent: "Edit last" }), + el(radio, { textContent: "Remove" }), + el("button", "Submit") + ) +); +document.head.append( + el("style", "form{ display: flex; flex-flow: column nowrap; }") +); +function radio({ textContent, checked= false }){ + return el("label").append( + el("input", { type: "radio", name: "op", value: textContent[0], checked }), + " ",textContent + ) +} diff --git a/docs_src/components/examples/observables/computations-abort.js b/docs_src/components/examples/observables/computations-abort.js index f504e7d..dcf7386 100644 --- a/docs_src/components/examples/observables/computations-abort.js +++ b/docs_src/components/examples/observables/computations-abort.js @@ -8,7 +8,7 @@ O.on(observable, v=> console.log("observable", v), { signal: ac.signal }); O.on(double, v=> console.log("double", v), { signal: ac.signal }); observable(observable()+1); -const interval= 5000; +const interval= 5 * 1000; const id= setInterval(()=> observable(observable()+1), interval); ac.signal.addEventListener("abort", ()=> setTimeout(()=> clearInterval(id), 2*interval)); diff --git a/docs_src/components/examples/observables/dom-attrs.js b/docs_src/components/examples/observables/dom-attrs.js new file mode 100644 index 0000000..4d7a336 --- /dev/null +++ b/docs_src/components/examples/observables/dom-attrs.js @@ -0,0 +1,15 @@ +import { O } from "deka-dom-el/observables"; +const count= O(0); + +import { el } from "deka-dom-el"; +document.body.append( + el("p", O(()=> "Currently: "+count())), + el("p", { classList: { red: O(()=> count()%2) }, dataset: { count }, textContent: "Attributes example" }) +); +document.head.append( + el("style", ".red { color: red; }") +); + +const interval= 5 * 1000; +setTimeout(clearInterval, 10*interval, + setInterval(()=> count(count()+1), interval)); diff --git a/docs_src/components/examples/observables/dom-el.js b/docs_src/components/examples/observables/dom-el.js new file mode 100644 index 0000000..e473df7 --- /dev/null +++ b/docs_src/components/examples/observables/dom-el.js @@ -0,0 +1,26 @@ +import { O } from "deka-dom-el/observables"; +const count= O(0, { + add(){ this.value= this.value + Math.round(Math.random()*10); } +}); +const numbers= O([ count() ], { + push(next){ this.value.push(next); } +}); + +import { el } from "deka-dom-el"; +document.body.append( + O.el(count, count=> count%2 + ? el("p", "Last number is odd.") + : el() + ), + el("p", "Lucky numbers:"), + el("ul").append( + O.el(numbers, numbers=> numbers.toReversed() + .map(n=> el("li", n))) + ) +); + +const interval= 5*1000; +setTimeout(clearInterval, 10*interval, setInterval(function(){ + O.action(count, "add"); + O.action(numbers, "push", count()); +}, interval)); diff --git a/docs_src/components/examples/observables/intro.js b/docs_src/components/examples/observables/intro.js index dd6bed6..fc0c53b 100644 --- a/docs_src/components/examples/observables/intro.js +++ b/docs_src/components/examples/observables/intro.js @@ -1,10 +1,6 @@ -// when NPM -import { O } from "deka-dom-el/observables"; -// https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js - -/** - * @type {ddeObservable} - * */ -/** - * @type {ddeActions} - * */ +// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-observables.js +import { O, observable } from "deka-dom-el/observables"; +O===observable +/** @type {ddeObservable} */ +/** @type {ddeAction} */ +/** @type {ddeActions} */ diff --git a/docs_src/components/examples/observables/observables.js b/docs_src/components/examples/observables/observables.js index c1e9d9c..d154991 100644 --- a/docs_src/components/examples/observables/observables.js +++ b/docs_src/components/examples/observables/observables.js @@ -4,5 +4,9 @@ const observable= O(0); // β — just reacts on observable changes O.on(observable, console.log); // γ — just updates the value -observable(observable()+1); -setInterval(()=> observable(observable()+1), 5000); +const update= ()=> observable(observable()+1); + +update(); +const interval= 5*1000; +setTimeout(clearInterval, 10*interval, + setInterval(update, interval)); diff --git a/docs_src/components/mnemonic/elements-init.js b/docs_src/components/mnemonic/elements-init.js new file mode 100644 index 0000000..011f63d --- /dev/null +++ b/docs_src/components/mnemonic/elements-init.js @@ -0,0 +1,25 @@ +import { el } from "deka-dom-el"; +import { mnemonicUl } from "../mnemonicUl.html.js"; + +export function mnemonic(){ + return mnemonicUl().append( + el("li").append( + el("code", "assign(, ...): "), " — assign properties to the element", + ), + el("li").append( + el("code", "el(, )[.append(...)]: "), " — simple element containing only text", + ), + el("li").append( + el("code", "el(, )[.append(...)]: "), " — element with more properties", + ), + el("li").append( + el("code", "el(, )[.append(...)]: "), " — using component represented by function", + ), + el("li").append( + el("code", "el(<...>, <...>, ...)"), " — see following page" + ), + el("li").append( + el("code", "elNS()()[.append(...)]: "), " — typically SVG elements", + ) + ); +} diff --git a/docs_src/components/mnemonic/events-init.js b/docs_src/components/mnemonic/events-init.js new file mode 100644 index 0000000..77252b0 --- /dev/null +++ b/docs_src/components/mnemonic/events-init.js @@ -0,0 +1,20 @@ +import { el } from "deka-dom-el"; +import { mnemonicUl } from "../mnemonicUl.html.js"; + +export function mnemonic(){ + return mnemonicUl().append( + el("li").append( + el("code", "on(, [, ])()"), " — just ", el("code", ".addEventListener(, [, ])") + ), + el("li").append( + el("code", "on.(, [, ])()"), " — corresponds to custom elemnets callbacks ", el("code", "Callback(...){...}"), + ". To connect to custom element see following page, else it is simulated by MutationObserver." + ), + el("li").append( + el("code", "dispatchEvent([, ])(element)"), " — just ", el("code", ".dispatchEvent(new Event([, ]))") + ), + el("li").append( + el("code", "dispatchEvent([, ])(element, detail)"), " — just ", el("code", ".dispatchEvent(new CustomEvent(, { detail, ... }))") + ), + ); +} diff --git a/docs_src/components/mnemonic/observables-init.js b/docs_src/components/mnemonic/observables-init.js new file mode 100644 index 0000000..d05b100 --- /dev/null +++ b/docs_src/components/mnemonic/observables-init.js @@ -0,0 +1,28 @@ +import { el } from "deka-dom-el"; +import { mnemonicUl } from "../mnemonicUl.html.js"; + +export function mnemonic(){ + return mnemonicUl().append( + el("li").append( + el("code", "O()"), " — observable: reactive value", + ), + el("li").append( + el("code", "O(()=> )"), " — observable: reactive value dependent on calculation using other observables", + ), + el("li").append( + el("code", "O.on(, [, ])"), " — listen to the observable value changes", + ), + el("li").append( + el("code", "O.clear(...)"), " — off and clear observables", + ), + el("li").append( + el("code", "O(, )"), " — observable: pattern to create complex reactive objects/arrays", + ), + el("li").append( + el("code", "O.action(, , ...)"), " — invoke an action for given observable" + ), + el("li").append( + el("code", "O.el(, )"), " — render partial dom structure (template) based on the current observable value", + ) + ); +} diff --git a/docs_src/components/mnemonicUl.html.js b/docs_src/components/mnemonicUl.html.js index 716d453..ffb0270 100644 --- a/docs_src/components/mnemonicUl.html.js +++ b/docs_src/components/mnemonicUl.html.js @@ -7,8 +7,8 @@ ${host} h3{ } `; import { el, simulateSlots } from "deka-dom-el"; -/** @param {Object} props @param {string} props.textContent */ -export function mnemonicUl({ textContent= "" }){ +/** @param {Object} [props] @param {string} [props.textContent] */ +export function mnemonicUl({ textContent= "" }= {}){ if(textContent) textContent= " – "+textContent return simulateSlots(el("div", { className: "notice" }).append( el(h3, "Mnemonic"+textContent), diff --git a/docs_src/global.css.js b/docs_src/global.css.js index f3dc507..c3878b2 100644 --- a/docs_src/global.css.js +++ b/docs_src/global.css.js @@ -20,7 +20,7 @@ body { @media (min-width:768px) { body{ grid-template-rows: auto auto; - grid-template-columns: calc(var(--body-max-width) / 3) auto; + grid-template-columns: calc(10 * var(--body-max-width) / 27) auto; grid-template-areas: "header header" "sidebar content" diff --git a/docs_src/p02-elements.html.js b/docs_src/p02-elements.html.js index 269a5b3..81c2699 100644 --- a/docs_src/p02-elements.html.js +++ b/docs_src/p02-elements.html.js @@ -3,7 +3,7 @@ import { simplePage } from "./layout/simplePage.html.js"; import { el } from "deka-dom-el"; import { example } from "./components/example.html.js"; import { h3 } from "./components/pageUtils.html.js"; -import { mnemonicUl } from "./components/mnemonicUl.html.js"; +import { mnemonic } from "./components/mnemonic/elements-init.js"; import { code } from "./components/code.html.js"; /** @param {string} url */ const fileURL= url=> new URL(url, import.meta.url); @@ -116,25 +116,6 @@ export function page({ pkg, info }){ ), el(example, { src: fileURL("./components/examples/elements/dekaElNS.js"), page_id }), - el(mnemonicUl).append( - el("li").append( - el("code", "assign(, ...): "), " — assign properties to the element", - ), - el("li").append( - el("code", "el(, )[.append(...)]: "), " — simple element containing only text", - ), - el("li").append( - el("code", "el(, )[.append(...)]: "), " — element with more properties", - ), - el("li").append( - el("code", "el(, )[.append(...)]: "), " — using component represented by function", - ), - el("li").append( - el("code", "el(<...>, <...>, ...)"), " — see following page" - ), - el("li").append( - el("code", "elNS()()[.append(...)]: "), " — typically SVG elements", - ) - ) + el(mnemonic) ); } diff --git a/docs_src/p03-events.html.js b/docs_src/p03-events.html.js index 8fe799d..b0def3a 100644 --- a/docs_src/p03-events.html.js +++ b/docs_src/p03-events.html.js @@ -3,7 +3,7 @@ import { simplePage } from "./layout/simplePage.html.js"; import { el } from "deka-dom-el"; import { example } from "./components/example.html.js"; import { h3 } from "./components/pageUtils.html.js"; -import { mnemonicUl } from "./components/mnemonicUl.html.js"; +import { mnemonic } from "./components/mnemonic/events-init.js"; import { code } from "./components/code.html.js"; /** @param {string} url */ const fileURL= url=> new URL(url, import.meta.url); @@ -113,20 +113,6 @@ export function page({ pkg, info }){ el("p", "The library also provides a method to dispatch the events."), el(example, { src: fileURL("./components/examples/events/compareDispatch.js"), page_id }), - el(mnemonicUl).append( - el("li").append( - el("code", "on(, [, ])()"), " — just ", el("code", ".addEventListener(, [, ])") - ), - el("li").append( - el("code", "on.(, [, ])()"), " — corresponds to custom elemnets callbacks ", el("code", "Callback(...){...}"), - ". To connect to custom element see following page, else it is simulated by MutationObserver." - ), - el("li").append( - el("code", "dispatchEvent([, ])(element)"), " — just ", el("code", ".dispatchEvent(new Event([, ]))") - ), - el("li").append( - el("code", "dispatchEvent([, ])(element, detail)"), " — just ", el("code", ".dispatchEvent(new CustomEvent(, { detail, ... }))") - ), - ), + el(mnemonic) ); } diff --git a/docs_src/p04-observables.html.js b/docs_src/p04-observables.html.js index 988eda5..90940a6 100644 --- a/docs_src/p04-observables.html.js +++ b/docs_src/p04-observables.html.js @@ -3,7 +3,7 @@ import { simplePage } from "./layout/simplePage.html.js"; import { el } from "deka-dom-el"; import { example } from "./components/example.html.js"; import { h3 } from "./components/pageUtils.html.js"; -import { mnemonicUl } from "./components/mnemonicUl.html.js"; +import { mnemonic } from "./components/mnemonic/observables-init.js"; import { code } from "./components/code.html.js"; /** @param {string} url */ const fileURL= url=> new URL(url, import.meta.url); @@ -48,28 +48,54 @@ export function page({ pkg, info }){ el("p").append( "Similarly to the ", el("code", "on"), " function to register DOM events listener.", " You can use ", el("code", "AbortController"), "/", el("code", "AbortSignal"), " to", - " ", el("em", "off"), "/stop listenning. For representing “live” piece of code computation pattern:" + " ", el("em", "off"), "/stop listenning. In example, you also found the way for representing", + " “live” piece of code computation pattern (derived observable):" ), el(example, { src: fileURL("./components/examples/observables/computations-abort.js"), page_id }), - el(mnemonicUl).append( - el("li").append( - el("code", "O()"), " — observable: reactive value", - ), - el("li").append( - el("code", "O(()=> )"), " — observable: reactive value dependent on calculation using other observables", - ), - el("li").append( - el("code", "O.on(, [, ])"), " — listen to the observable value changes", - ), - el("li").append( - el("code", "O.clear(...)"), " — off and clear observables", - ), - el("li").append( - el("code", "O(, )"), " — observable: pattern to create complex reactive objects/arrays", - ), - el("li").append( - el("code", "O.action(, , ...)"), " — invoke an action for given observable" - ) + + el(h3, "Observables and actions"), + el("p").append( + el("code", "O(/* primitive */)"), " allows you to declare simple reactive variables, typically", + " around ", el("em", "immutable"), " ", el("a", { textContent: "primitive types", title: "Primitive | MDN", href: "https://developer.mozilla.org/en-US/docs/Glossary/Primitive" }), ".", + " ", + "However, it may also be necessary to use reactive arrays, objects, or other complex reactive structures." ), + el(example, { src: fileURL("./components/examples/observables/actions-demo.js"), page_id }), + el("p", "…but typical user-case is object/array (maps, sets and other mutable objects):"), + el(example, { src: fileURL("./components/examples/observables/actions-todos.js"), page_id }), + el("p").append( + "In some way, you can compare it with ", el("a", { textContent: "useReducer", href: "https://react.dev/reference/react/useReducer", title: "useReducer hook | React docs" }), + " hook from React. So, the ", el("code", "O(, )"), " pattern creates", + " a store “machine”. We can then invoke (dispatch) registered action by calling", + " ", el("code", "O.action(, , ...)"), " after the action call", + " the observable calls all its listeners. This can be stopped by calling ", el("code", "this.stopPropagation()"), + " in the method representing the given action. As it can be seen in examples, the “store” value is", + " available also in the function for given action (", el("code", "this.value"), ")." + ), + + el(h3, "Reactive DOM attributes and elements"), + el("p", "There are on basic level two distinc situation to mirror dynamic value into the DOM/UI"), + el("ol").append( + el("li", "to change some attribute(s) of existing element(s)"), + el("li", "to generate elements itself dynamically – this covers conditions and loops") + ), + el(example, { src: fileURL("./components/examples/observables/dom-attrs.js"), page_id }), + el("p").append( + "To derived attribute based on value of observable variable just use the observable as", + " a value of the attribute (", el("code", "assign(element, { attribute: O('value') })"), ").", + " ", el("code", "assign"), "/", el("code", "el"), " provides ways to glue reactive attributes/classes", + " more granularly into the DOM. Just use dedicated build-in attributes ", el("code", "dataset"), ", ", + el("code", "ariaset"), " and ", el("code", "classList"), "." + ), + el("p").append( + "For computation, you can use the derived observable (see above) like ", el("code", "assign(element, { textContent: O(()=> 'Hello '+WorldObservable()) })"), "." + ), + el("p").append( + "To represent part of the template filled dynamically based on the observable value use ", el("code", "O.el(observable, DOMgenerator)"), ".", + " This was already used in the todo example above or see:" + ), + el(example, { src: fileURL("./components/examples/observables/dom-el.js"), page_id }), + + el(mnemonic) ); } diff --git a/index.d.ts b/index.d.ts index c6bbb02..5f022c0 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,3 +1,5 @@ +import { Observable } from "./observables"; + type CustomElementTagNameMap= { '#text': Text, '#comment': Comment } declare global { interface ddePublicElementTagNameMap{ @@ -18,20 +20,21 @@ type AttrsModified= { /** * Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API). */ - style: string | Partial + style: string | Partial | Observable | Partial<{ [K in keyof CSSStyleDeclaration]: Observable }> /** * Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` for others. */ - classList: Record, + classList: Record>, /** * By default simiral to `className`, but also supports `string[]` * */ - className: string | (string|boolean|undefined)[]; + className: string | (string|boolean|undefined|Observable)[]; /** * Sets `aria-*` simiraly to `dataset` * */ - ariaset: Record, -} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, string> & Record<`.${string}`, any> + ariaset: Record>, +} & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, string|Observable> & Record<`.${string}`, any> +type _fromElsInterfaces= Omit; /** * Just element attributtes * @@ -40,17 +43,28 @@ type AttrsModified= { * There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives. * @private */ -type ElementAttributes= Omit & AttrsModified; +type ElementAttributes= Partial<_fromElsInterfaces & { [K in keyof _fromElsInterfaces]: Observable<_fromElsInterfaces[K], any> } & AttrsModified>; export function classListDeclarative(element: El, classList: AttrsModified["classList"]): El -export function assign(element: El, ...attrs_array: Partial>[]): El +export function assign(element: El, ...attrs_array: ElementAttributes[]): El export function assignAttribute>(element: El, attr: ATT, value: ElementAttributes[ATT]): ElementAttributes[ATT] type ExtendedHTMLElementTagNameMap= ddeHTMLElementTagNameMap & CustomElementTagNameMap & ddePublicElementTagNameMap -export function el( +export function el< + TAG extends string, + EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : ddeHTMLElement) +>( tag_name: TAG, - attrs?: string | Partial>, - ...addons: ddeElementAddon[] -): ExtendedHTMLElementTagNameMap[TAG] + attrs?: ElementAttributes, + ...addons: ddeElementAddon[] +): EL +export function el< + TAG extends string, + EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : ddeHTMLElement) +>( + tag_name: TAG, + attrs?: string | Observable, + ...addons: ddeElementAddon[] +): EL export function el( tag_name?: "<>", ): ddeDocumentFragment @@ -62,12 +76,7 @@ export function el< attrs?: A | string, ...addons: ddeElementAddon>[] ): ReturnType - -export function el( - tag_name: string, - attrs?: string | Record, - ...addons: ddeElementAddon[] -): ddeHTMLElement +export { el as createElement } export function elNS( namespace: "http://www.w3.org/2000/svg" @@ -90,6 +99,7 @@ export function elNS( attrs?: string | Record, ...addons: ddeElementAddon[] )=> SupportedElement +export { elNS as createElementNS } export function chainableAppend(el: EL): EL; export function simulateSlots(el: EL): EL @@ -249,71 +259,6 @@ declare global{ "ul": ddeHTMLUListElement; "video": ddeHTMLVideoElement; } - interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend; } - interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend; } - interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend; } - interface ddeHTMLBaseElement extends HTMLBaseElement{ append: ddeAppend; } - interface ddeHTMLQuoteElement extends HTMLQuoteElement{ append: ddeAppend; } - interface ddeHTMLBodyElement extends HTMLBodyElement{ append: ddeAppend; } - interface ddeHTMLBRElement extends HTMLBRElement{ append: ddeAppend; } - interface ddeHTMLButtonElement extends HTMLButtonElement{ append: ddeAppend; } - interface ddeHTMLCanvasElement extends HTMLCanvasElement{ append: ddeAppend; } - interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement{ append: ddeAppend; } - interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } - interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } - interface ddeHTMLDataElement extends HTMLDataElement{ append: ddeAppend; } - interface ddeHTMLDataListElement extends HTMLDataListElement{ append: ddeAppend; } - interface ddeHTMLModElement extends HTMLModElement{ append: ddeAppend; } - interface ddeHTMLDetailsElement extends HTMLDetailsElement{ append: ddeAppend; } - interface ddeHTMLDialogElement extends HTMLDialogElement{ append: ddeAppend; } - interface ddeHTMLDivElement extends HTMLDivElement{ append: ddeAppend; } - interface ddeHTMLDListElement extends HTMLDListElement{ append: ddeAppend; } - interface ddeHTMLEmbedElement extends HTMLEmbedElement{ append: ddeAppend; } - interface ddeHTMLFieldSetElement extends HTMLFieldSetElement{ append: ddeAppend; } - interface ddeHTMLFormElement extends HTMLFormElement{ append: ddeAppend; } - interface ddeHTMLHeadingElement extends HTMLHeadingElement{ append: ddeAppend; } - interface ddeHTMLHeadElement extends HTMLHeadElement{ append: ddeAppend; } - interface ddeHTMLHRElement extends HTMLHRElement{ append: ddeAppend; } - interface ddeHTMLHtmlElement extends HTMLHtmlElement{ append: ddeAppend; } - interface ddeHTMLIFrameElement extends HTMLIFrameElement{ append: ddeAppend; } - interface ddeHTMLImageElement extends HTMLImageElement{ append: ddeAppend; } - interface ddeHTMLInputElement extends HTMLInputElement{ append: ddeAppend; } - interface ddeHTMLLabelElement extends HTMLLabelElement{ append: ddeAppend; } - interface ddeHTMLLegendElement extends HTMLLegendElement{ append: ddeAppend; } - interface ddeHTMLLIElement extends HTMLLIElement{ append: ddeAppend; } - interface ddeHTMLLinkElement extends HTMLLinkElement{ append: ddeAppend; } - interface ddeHTMLMapElement extends HTMLMapElement{ append: ddeAppend; } - interface ddeHTMLMenuElement extends HTMLMenuElement{ append: ddeAppend; } - interface ddeHTMLMetaElement extends HTMLMetaElement{ append: ddeAppend; } - interface ddeHTMLMeterElement extends HTMLMeterElement{ append: ddeAppend; } - interface ddeHTMLObjectElement extends HTMLObjectElement{ append: ddeAppend; } - interface ddeHTMLOListElement extends HTMLOListElement{ append: ddeAppend; } - interface ddeHTMLOptGroupElement extends HTMLOptGroupElement{ append: ddeAppend; } - interface ddeHTMLOptionElement extends HTMLOptionElement{ append: ddeAppend; } - interface ddeHTMLOutputElement extends HTMLOutputElement{ append: ddeAppend; } - interface ddeHTMLParagraphElement extends HTMLParagraphElement{ append: ddeAppend; } - interface ddeHTMLPictureElement extends HTMLPictureElement{ append: ddeAppend; } - interface ddeHTMLPreElement extends HTMLPreElement{ append: ddeAppend; } - interface ddeHTMLProgressElement extends HTMLProgressElement{ append: ddeAppend; } - interface ddeHTMLScriptElement extends HTMLScriptElement{ append: ddeAppend; } - interface ddeHTMLSelectElement extends HTMLSelectElement{ append: ddeAppend; } - interface ddeHTMLSlotElement extends HTMLSlotElement{ append: ddeAppend; } - interface ddeHTMLSourceElement extends HTMLSourceElement{ append: ddeAppend; } - interface ddeHTMLSpanElement extends HTMLSpanElement{ append: ddeAppend; } - interface ddeHTMLStyleElement extends HTMLStyleElement{ append: ddeAppend; } - interface ddeHTMLTableElement extends HTMLTableElement{ append: ddeAppend; } - interface ddeHTMLTableSectionElement extends HTMLTableSectionElement{ append: ddeAppend; } - interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } - interface ddeHTMLTemplateElement extends HTMLTemplateElement{ append: ddeAppend; } - interface ddeHTMLTextAreaElement extends HTMLTextAreaElement{ append: ddeAppend; } - interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } - interface ddeHTMLTimeElement extends HTMLTimeElement{ append: ddeAppend; } - interface ddeHTMLTitleElement extends HTMLTitleElement{ append: ddeAppend; } - interface ddeHTMLTableRowElement extends HTMLTableRowElement{ append: ddeAppend; } - interface ddeHTMLTrackElement extends HTMLTrackElement{ append: ddeAppend; } - interface ddeHTMLUListElement extends HTMLUListElement{ append: ddeAppend; } - interface ddeHTMLVideoElement extends HTMLVideoElement{ append: ddeAppend; } - interface ddeSVGElementTagNameMap { "a": ddeSVGAElement; "animate": ddeSVGAnimateElement; @@ -379,67 +324,132 @@ declare global{ "use": ddeSVGUseElement; "view": ddeSVGViewElement; } - interface ddeSVGAElement extends SVGAElement{ append: ddeAppend; } - interface ddeSVGAnimateElement extends SVGAnimateElement{ append: ddeAppend; } - interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement{ append: ddeAppend; } - interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement{ append: ddeAppend; } - interface ddeSVGCircleElement extends SVGCircleElement{ append: ddeAppend; } - interface ddeSVGClipPathElement extends SVGClipPathElement{ append: ddeAppend; } - interface ddeSVGDefsElement extends SVGDefsElement{ append: ddeAppend; } - interface ddeSVGDescElement extends SVGDescElement{ append: ddeAppend; } - interface ddeSVGEllipseElement extends SVGEllipseElement{ append: ddeAppend; } - interface ddeSVGFEBlendElement extends SVGFEBlendElement{ append: ddeAppend; } - interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement{ append: ddeAppend; } - interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement{ append: ddeAppend; } - interface ddeSVGFECompositeElement extends SVGFECompositeElement{ append: ddeAppend; } - interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement{ append: ddeAppend; } - interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement{ append: ddeAppend; } - interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement{ append: ddeAppend; } - interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement{ append: ddeAppend; } - interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement{ append: ddeAppend; } - interface ddeSVGFEFloodElement extends SVGFEFloodElement{ append: ddeAppend; } - interface ddeSVGFEFuncAElement extends SVGFEFuncAElement{ append: ddeAppend; } - interface ddeSVGFEFuncBElement extends SVGFEFuncBElement{ append: ddeAppend; } - interface ddeSVGFEFuncGElement extends SVGFEFuncGElement{ append: ddeAppend; } - interface ddeSVGFEFuncRElement extends SVGFEFuncRElement{ append: ddeAppend; } - interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement{ append: ddeAppend; } - interface ddeSVGFEImageElement extends SVGFEImageElement{ append: ddeAppend; } - interface ddeSVGFEMergeElement extends SVGFEMergeElement{ append: ddeAppend; } - interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement{ append: ddeAppend; } - interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement{ append: ddeAppend; } - interface ddeSVGFEOffsetElement extends SVGFEOffsetElement{ append: ddeAppend; } - interface ddeSVGFEPointLightElement extends SVGFEPointLightElement{ append: ddeAppend; } - interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement{ append: ddeAppend; } - interface ddeSVGFESpotLightElement extends SVGFESpotLightElement{ append: ddeAppend; } - interface ddeSVGFETileElement extends SVGFETileElement{ append: ddeAppend; } - interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement{ append: ddeAppend; } - interface ddeSVGFilterElement extends SVGFilterElement{ append: ddeAppend; } - interface ddeSVGForeignObjectElement extends SVGForeignObjectElement{ append: ddeAppend; } - interface ddeSVGGElement extends SVGGElement{ append: ddeAppend; } - interface ddeSVGImageElement extends SVGImageElement{ append: ddeAppend; } - interface ddeSVGLineElement extends SVGLineElement{ append: ddeAppend; } - interface ddeSVGLinearGradientElement extends SVGLinearGradientElement{ append: ddeAppend; } - interface ddeSVGMarkerElement extends SVGMarkerElement{ append: ddeAppend; } - interface ddeSVGMaskElement extends SVGMaskElement{ append: ddeAppend; } - interface ddeSVGMetadataElement extends SVGMetadataElement{ append: ddeAppend; } - interface ddeSVGMPathElement extends SVGMPathElement{ append: ddeAppend; } - interface ddeSVGPathElement extends SVGPathElement{ append: ddeAppend; } - interface ddeSVGPatternElement extends SVGPatternElement{ append: ddeAppend; } - interface ddeSVGPolygonElement extends SVGPolygonElement{ append: ddeAppend; } - interface ddeSVGPolylineElement extends SVGPolylineElement{ append: ddeAppend; } - interface ddeSVGRadialGradientElement extends SVGRadialGradientElement{ append: ddeAppend; } - interface ddeSVGRectElement extends SVGRectElement{ append: ddeAppend; } - interface ddeSVGScriptElement extends SVGScriptElement{ append: ddeAppend; } - interface ddeSVGSetElement extends SVGSetElement{ append: ddeAppend; } - interface ddeSVGStopElement extends SVGStopElement{ append: ddeAppend; } - interface ddeSVGStyleElement extends SVGStyleElement{ append: ddeAppend; } - interface ddeSVGSVGElement extends SVGSVGElement{ append: ddeAppend; } - interface ddeSVGSwitchElement extends SVGSwitchElement{ append: ddeAppend; } - interface ddeSVGSymbolElement extends SVGSymbolElement{ append: ddeAppend; } - interface ddeSVGTextElement extends SVGTextElement{ append: ddeAppend; } - interface ddeSVGTextPathElement extends SVGTextPathElement{ append: ddeAppend; } - interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend; } - interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend; } - interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend; } - interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend; } } + +interface ddeHTMLAnchorElement extends HTMLAnchorElement{ append: ddeAppend; } +interface ddeHTMLAreaElement extends HTMLAreaElement{ append: ddeAppend; } +interface ddeHTMLAudioElement extends HTMLAudioElement{ append: ddeAppend; } +interface ddeHTMLBaseElement extends HTMLBaseElement{ append: ddeAppend; } +interface ddeHTMLQuoteElement extends HTMLQuoteElement{ append: ddeAppend; } +interface ddeHTMLBodyElement extends HTMLBodyElement{ append: ddeAppend; } +interface ddeHTMLBRElement extends HTMLBRElement{ append: ddeAppend; } +interface ddeHTMLButtonElement extends HTMLButtonElement{ append: ddeAppend; } +interface ddeHTMLCanvasElement extends HTMLCanvasElement{ append: ddeAppend; } +interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement{ append: ddeAppend; } +interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } +interface ddeHTMLTableColElement extends HTMLTableColElement{ append: ddeAppend; } +interface ddeHTMLDataElement extends HTMLDataElement{ append: ddeAppend; } +interface ddeHTMLDataListElement extends HTMLDataListElement{ append: ddeAppend; } +interface ddeHTMLModElement extends HTMLModElement{ append: ddeAppend; } +interface ddeHTMLDetailsElement extends HTMLDetailsElement{ append: ddeAppend; } +interface ddeHTMLDialogElement extends HTMLDialogElement{ append: ddeAppend; } +interface ddeHTMLDivElement extends HTMLDivElement{ append: ddeAppend; } +interface ddeHTMLDListElement extends HTMLDListElement{ append: ddeAppend; } +interface ddeHTMLEmbedElement extends HTMLEmbedElement{ append: ddeAppend; } +interface ddeHTMLFieldSetElement extends HTMLFieldSetElement{ append: ddeAppend; } +interface ddeHTMLFormElement extends HTMLFormElement{ append: ddeAppend; } +interface ddeHTMLHeadingElement extends HTMLHeadingElement{ append: ddeAppend; } +interface ddeHTMLHeadElement extends HTMLHeadElement{ append: ddeAppend; } +interface ddeHTMLHRElement extends HTMLHRElement{ append: ddeAppend; } +interface ddeHTMLHtmlElement extends HTMLHtmlElement{ append: ddeAppend; } +interface ddeHTMLIFrameElement extends HTMLIFrameElement{ append: ddeAppend; } +interface ddeHTMLImageElement extends HTMLImageElement{ append: ddeAppend; } +interface ddeHTMLInputElement extends HTMLInputElement{ append: ddeAppend; } +interface ddeHTMLLabelElement extends HTMLLabelElement{ append: ddeAppend; } +interface ddeHTMLLegendElement extends HTMLLegendElement{ append: ddeAppend; } +interface ddeHTMLLIElement extends HTMLLIElement{ append: ddeAppend; } +interface ddeHTMLLinkElement extends HTMLLinkElement{ append: ddeAppend; } +interface ddeHTMLMapElement extends HTMLMapElement{ append: ddeAppend; } +interface ddeHTMLMenuElement extends HTMLMenuElement{ append: ddeAppend; } +interface ddeHTMLMetaElement extends HTMLMetaElement{ append: ddeAppend; } +interface ddeHTMLMeterElement extends HTMLMeterElement{ append: ddeAppend; } +interface ddeHTMLObjectElement extends HTMLObjectElement{ append: ddeAppend; } +interface ddeHTMLOListElement extends HTMLOListElement{ append: ddeAppend; } +interface ddeHTMLOptGroupElement extends HTMLOptGroupElement{ append: ddeAppend; } +interface ddeHTMLOptionElement extends HTMLOptionElement{ append: ddeAppend; } +interface ddeHTMLOutputElement extends HTMLOutputElement{ append: ddeAppend; } +interface ddeHTMLParagraphElement extends HTMLParagraphElement{ append: ddeAppend; } +interface ddeHTMLPictureElement extends HTMLPictureElement{ append: ddeAppend; } +interface ddeHTMLPreElement extends HTMLPreElement{ append: ddeAppend; } +interface ddeHTMLProgressElement extends HTMLProgressElement{ append: ddeAppend; } +interface ddeHTMLScriptElement extends HTMLScriptElement{ append: ddeAppend; } +interface ddeHTMLSelectElement extends HTMLSelectElement{ append: ddeAppend; } +interface ddeHTMLSlotElement extends HTMLSlotElement{ append: ddeAppend; } +interface ddeHTMLSourceElement extends HTMLSourceElement{ append: ddeAppend; } +interface ddeHTMLSpanElement extends HTMLSpanElement{ append: ddeAppend; } +interface ddeHTMLStyleElement extends HTMLStyleElement{ append: ddeAppend; } +interface ddeHTMLTableElement extends HTMLTableElement{ append: ddeAppend; } +interface ddeHTMLTableSectionElement extends HTMLTableSectionElement{ append: ddeAppend; } +interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } +interface ddeHTMLTemplateElement extends HTMLTemplateElement{ append: ddeAppend; } +interface ddeHTMLTextAreaElement extends HTMLTextAreaElement{ append: ddeAppend; } +interface ddeHTMLTableCellElement extends HTMLTableCellElement{ append: ddeAppend; } +interface ddeHTMLTimeElement extends HTMLTimeElement{ append: ddeAppend; } +interface ddeHTMLTitleElement extends HTMLTitleElement{ append: ddeAppend; } +interface ddeHTMLTableRowElement extends HTMLTableRowElement{ append: ddeAppend; } +interface ddeHTMLTrackElement extends HTMLTrackElement{ append: ddeAppend; } +interface ddeHTMLUListElement extends HTMLUListElement{ append: ddeAppend; } +interface ddeHTMLVideoElement extends HTMLVideoElement{ append: ddeAppend; } +interface ddeSVGAElement extends SVGAElement{ append: ddeAppend; } +interface ddeSVGAnimateElement extends SVGAnimateElement{ append: ddeAppend; } +interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement{ append: ddeAppend; } +interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement{ append: ddeAppend; } +interface ddeSVGCircleElement extends SVGCircleElement{ append: ddeAppend; } +interface ddeSVGClipPathElement extends SVGClipPathElement{ append: ddeAppend; } +interface ddeSVGDefsElement extends SVGDefsElement{ append: ddeAppend; } +interface ddeSVGDescElement extends SVGDescElement{ append: ddeAppend; } +interface ddeSVGEllipseElement extends SVGEllipseElement{ append: ddeAppend; } +interface ddeSVGFEBlendElement extends SVGFEBlendElement{ append: ddeAppend; } +interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement{ append: ddeAppend; } +interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement{ append: ddeAppend; } +interface ddeSVGFECompositeElement extends SVGFECompositeElement{ append: ddeAppend; } +interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement{ append: ddeAppend; } +interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement{ append: ddeAppend; } +interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement{ append: ddeAppend; } +interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement{ append: ddeAppend; } +interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement{ append: ddeAppend; } +interface ddeSVGFEFloodElement extends SVGFEFloodElement{ append: ddeAppend; } +interface ddeSVGFEFuncAElement extends SVGFEFuncAElement{ append: ddeAppend; } +interface ddeSVGFEFuncBElement extends SVGFEFuncBElement{ append: ddeAppend; } +interface ddeSVGFEFuncGElement extends SVGFEFuncGElement{ append: ddeAppend; } +interface ddeSVGFEFuncRElement extends SVGFEFuncRElement{ append: ddeAppend; } +interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement{ append: ddeAppend; } +interface ddeSVGFEImageElement extends SVGFEImageElement{ append: ddeAppend; } +interface ddeSVGFEMergeElement extends SVGFEMergeElement{ append: ddeAppend; } +interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement{ append: ddeAppend; } +interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement{ append: ddeAppend; } +interface ddeSVGFEOffsetElement extends SVGFEOffsetElement{ append: ddeAppend; } +interface ddeSVGFEPointLightElement extends SVGFEPointLightElement{ append: ddeAppend; } +interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement{ append: ddeAppend; } +interface ddeSVGFESpotLightElement extends SVGFESpotLightElement{ append: ddeAppend; } +interface ddeSVGFETileElement extends SVGFETileElement{ append: ddeAppend; } +interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement{ append: ddeAppend; } +interface ddeSVGFilterElement extends SVGFilterElement{ append: ddeAppend; } +interface ddeSVGForeignObjectElement extends SVGForeignObjectElement{ append: ddeAppend; } +interface ddeSVGGElement extends SVGGElement{ append: ddeAppend; } +interface ddeSVGImageElement extends SVGImageElement{ append: ddeAppend; } +interface ddeSVGLineElement extends SVGLineElement{ append: ddeAppend; } +interface ddeSVGLinearGradientElement extends SVGLinearGradientElement{ append: ddeAppend; } +interface ddeSVGMarkerElement extends SVGMarkerElement{ append: ddeAppend; } +interface ddeSVGMaskElement extends SVGMaskElement{ append: ddeAppend; } +interface ddeSVGMetadataElement extends SVGMetadataElement{ append: ddeAppend; } +interface ddeSVGMPathElement extends SVGMPathElement{ append: ddeAppend; } +interface ddeSVGPathElement extends SVGPathElement{ append: ddeAppend; } +interface ddeSVGPatternElement extends SVGPatternElement{ append: ddeAppend; } +interface ddeSVGPolygonElement extends SVGPolygonElement{ append: ddeAppend; } +interface ddeSVGPolylineElement extends SVGPolylineElement{ append: ddeAppend; } +interface ddeSVGRadialGradientElement extends SVGRadialGradientElement{ append: ddeAppend; } +interface ddeSVGRectElement extends SVGRectElement{ append: ddeAppend; } +interface ddeSVGScriptElement extends SVGScriptElement{ append: ddeAppend; } +interface ddeSVGSetElement extends SVGSetElement{ append: ddeAppend; } +interface ddeSVGStopElement extends SVGStopElement{ append: ddeAppend; } +interface ddeSVGStyleElement extends SVGStyleElement{ append: ddeAppend; } +interface ddeSVGSVGElement extends SVGSVGElement{ append: ddeAppend; } +interface ddeSVGSwitchElement extends SVGSwitchElement{ append: ddeAppend; } +interface ddeSVGSymbolElement extends SVGSymbolElement{ append: ddeAppend; } +interface ddeSVGTextElement extends SVGTextElement{ append: ddeAppend; } +interface ddeSVGTextPathElement extends SVGTextPathElement{ append: ddeAppend; } +interface ddeSVGTitleElement extends SVGTitleElement{ append: ddeAppend; } +interface ddeSVGTSpanElement extends SVGTSpanElement{ append: ddeAppend; } +interface ddeSVGUseElement extends SVGUseElement{ append: ddeAppend; } +interface ddeSVGViewElement extends SVGViewElement{ append: ddeAppend; } diff --git a/observables.d.ts b/observables.d.ts index 7925f4d..2c17223 100644 --- a/observables.d.ts +++ b/observables.d.ts @@ -1,8 +1,8 @@ export type Observable= (set?: V)=> V & A; -type Action= (this: { value: V }, ...a: any[])=> typeof observable._ | void; -type SymbolOnclear= Symbol; -type SymbolObservable= Symbol; -type Actions= Record>; +type Action= (this: { value: V, stopPropagation(): void }, ...a: any[])=> typeof observable._ | void; +//type SymbolObservable= Symbol; +type SymbolOnclear= symbol; +type Actions= Record>; interface observable{ _: Symbol /** @@ -42,7 +42,7 @@ interface observable{ clear(...observables: Observable[]): void; on(observable: Observable, onchange: (a: T)=> void, options?: AddEventListenerOptions): void; symbols: { - observable: SymbolObservable; + //observable: SymbolObservable; onclear: SymbolOnclear; } /** @@ -52,7 +52,7 @@ interface observable{ * S.el(listS, list=> list.map(li=> el("li", li))); * ``` * */ - el(observable: Observable, el: (v: S)=> Element | Element[]): DocumentFragment; + el(observable: Observable, el: (v: S)=> Element | Element[] | DocumentFragment): DocumentFragment; attribute(name: string, initial?: string): Observable; } @@ -60,5 +60,6 @@ export const observable: observable; export const O: observable; declare global { type ddeObservable= Observable; + type ddeAction= Action type ddeActions= Actions } diff --git a/src/observables-lib.js b/src/observables-lib.js index cfad2e2..53ddc0f 100644 --- a/src/observables-lib.js +++ b/src/observables-lib.js @@ -60,7 +60,7 @@ observable.on= function on(o, listener, options= {}){ //TODO cleanup when observable removed }; observable.symbols= { - observable: mark, + //observable: mark, onclear: Symbol.for("Observable.onclear") }; observable.clear= function(...observables){