simplyflow 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -529,8 +529,11 @@
529
529
  // src/dom.mjs
530
530
  var dom_exports = {};
531
531
  __export(dom_exports, {
532
- signal: () => signal2
532
+ signal: () => signal2,
533
+ trackDomField: () => trackDomField,
534
+ trackDomList: () => trackDomList
533
535
  });
536
+ var domSignals = /* @__PURE__ */ new WeakMap();
534
537
  var domSignalHandler = {
535
538
  get: (target, property, receiver) => {
536
539
  if (property === Symbol.xRay) {
@@ -634,6 +637,65 @@
634
637
  }
635
638
  }
636
639
  }
640
+ function trackDomList(element2) {
641
+ const path = this.getBindingPath(element2);
642
+ if (!path) {
643
+ throw new Error("Could not find binding path for element", { cause: element2 });
644
+ }
645
+ const s = signal2(element2, {
646
+ childList: true
647
+ });
648
+ throttledEffect(() => {
649
+ const children = Array.from(s.children);
650
+ untracked(() => {
651
+ batch(() => {
652
+ let key = 0;
653
+ const currentList = getValueByPath(this.options.root, path);
654
+ const source = currentList.slice();
655
+ for (const item of children) {
656
+ if (item.tagName === "TEMPLATE") {
657
+ continue;
658
+ }
659
+ if (item.dataset.flowKey) {
660
+ if (item.dataset.flowKey != key) {
661
+ setValueByPath(
662
+ this.options.root,
663
+ path + "." + key,
664
+ source[item.dataset.flowKey]
665
+ );
666
+ }
667
+ key++;
668
+ }
669
+ }
670
+ if (currentList.length > key) {
671
+ currentList.length = key;
672
+ }
673
+ });
674
+ });
675
+ });
676
+ }
677
+ function trackDomField(element2, props, valueIsString) {
678
+ if (domSignals.has(element2)) {
679
+ return;
680
+ }
681
+ const path = this.getBindingPath(element2);
682
+ if (!path) {
683
+ throw new Error("Could not find binding path for element", { cause: element2 });
684
+ }
685
+ const s = signal2(element2);
686
+ domSignals.set(element2, s);
687
+ batch(() => {
688
+ throttledEffect(() => {
689
+ let updateValue = s.innerHTML;
690
+ if (!valueIsString) {
691
+ updateValue = getProperties(s, ...props);
692
+ }
693
+ untracked(() => {
694
+ setValueByPath(this.options.root, path, updateValue);
695
+ });
696
+ });
697
+ });
698
+ }
637
699
 
638
700
  // src/bind.render.mjs
639
701
  function field(context) {
@@ -789,37 +851,7 @@
789
851
  }
790
852
  }
791
853
  if (this.options.twoway) {
792
- const s = signal2(context.element, {
793
- childList: true
794
- });
795
- throttledEffect(() => {
796
- const children = Array.from(s.children);
797
- batch(() => {
798
- untracked(() => {
799
- let key = 0;
800
- const currentList = context.value.slice();
801
- for (const item of children) {
802
- if (item.tagName === "TEMPLATE") {
803
- continue;
804
- }
805
- if (item.dataset.flowKey) {
806
- if (item.dataset.flowKey != key) {
807
- setValueByPath(
808
- this.options.root,
809
- context.path + "." + key,
810
- currentList[item.dataset.flowKey]
811
- );
812
- }
813
- key++;
814
- }
815
- }
816
- if (context.value.length > key) {
817
- const source = getValueByPath(this.options.root, context.path);
818
- source.length = key;
819
- }
820
- });
821
- });
822
- });
854
+ trackDomList.call(this, context.element);
823
855
  }
824
856
  }
825
857
  function objectByTemplates(context) {
@@ -996,7 +1028,6 @@
996
1028
  });
997
1029
  }
998
1030
  }
999
- var domSignals = /* @__PURE__ */ new WeakMap();
1000
1031
  function element(context, ...extraprops) {
1001
1032
  const el = context.element;
1002
1033
  let value = context.value;
@@ -1011,26 +1042,8 @@
1011
1042
  const props = ["innerHTML", "title", "id", "className"].concat(extraprops);
1012
1043
  setProperties(el, value, ...props);
1013
1044
  if (this.options.twoway) {
1014
- batch(() => {
1015
- updateProperties.call(this, context, props, valueIsString);
1016
- });
1017
- }
1018
- }
1019
- function updateProperties(context, props, valueIsString) {
1020
- if (domSignals.has(context.element)) {
1021
- return;
1045
+ trackDomField.call(this, context.element, props, valueIsString);
1022
1046
  }
1023
- const s = signal2(context.element);
1024
- domSignals.set(context.element, s);
1025
- throttledEffect(() => {
1026
- let updateValue = s.innerHTML;
1027
- if (!valueIsString) {
1028
- updateValue = getProperties(s, ...props);
1029
- }
1030
- untracked(() => {
1031
- setValueByPath(this.options.root, context.path, updateValue);
1032
- });
1033
- });
1034
1047
  }
1035
1048
  function setProperties(el, data, ...properties) {
1036
1049
  if (!data || typeof data !== "object") {
@@ -1,2 +1,2 @@
1
- (()=>{var Ee=Object.defineProperty;var W=(e,t)=>{for(var n in t)Ee(e,n,{get:t[n],enumerable:!0})};var _={};W(_,{addTracer:()=>Me,batch:()=>T,clockEffect:()=>ie,clone:()=>Ce,destroy:()=>K,effect:()=>re,makeContext:()=>y,notifyGet:()=>v,notifySet:()=>g,signal:()=>A,signals:()=>h,throttledEffect:()=>b,trace:()=>ke,untracked:()=>V});Symbol.iterate||(Symbol.iterate=Symbol("iterate"));Symbol.xRay||(Symbol.xRay=Symbol("xRay"));Symbol.Signal||(Symbol.Signal=Symbol("Signal"));var ve={get:(e,t,n)=>{if(t===Symbol.xRay)return e;if(t===Symbol.Signal)return!0;let r=e?.[t];return v(n,t),typeof r=="function"?Array.isArray(e)?(...i)=>{let s=e.length,o=r.apply(n,i);return s!=e.length&&g(n,y("length",{was:s,now:e.length})),o}:e instanceof Set||e instanceof Map?(...i)=>{let s=e.size,o=r.apply(e,i);return s!=e.size&&g(n,y("size",{was:s,now:e.size})),["set","add","clear","delete"].includes(t)&&g(n,y({entries:{},forEach:{},has:{},keys:{},values:{},[Symbol.iterator]:{}})),o}:e instanceof HTMLElement||e instanceof Number||e instanceof String||e instanceof Boolean?r.bind(e):r.bind(n):r&&typeof r=="object"?A(r):r},set:(e,t,n,r)=>{let i=e[t];return i!==n&&(e[t]=n,g(r,y(t,{was:i,now:n}))),typeof i>"u"&&(g(r,y(Symbol.iterate,{})),g(r,y("length",{}))),!0},has:(e,t)=>{let n=h.get(e);return n&&v(n,t),Object.hasOwn(e,t)},deleteProperty:(e,t)=>{if(typeof e[t]<"u"){let n=e[t];delete e[t];let r=h.get(e);g(r,y(t,{delete:!0,was:n}))}return!0},defineProperty:(e,t,n)=>{if(typeof e[t]>"u"){let r=h.get(e);g(r,y(Symbol.iterate,{}))}return Object.defineProperty(e,t,n)},ownKeys:e=>{let t=h.get(e);return v(t,Symbol.iterate),Reflect.ownKeys(e)}},h=new WeakMap;function A(e){return e||(e={}),e[Symbol.Signal]?e:(h.has(e)||h.set(e,new Proxy(e,ve)),h.get(e))}var z=[],I=!1;function ke(e,t){if(typeof e=="function")I=!0,e(),I=!1;else return ne(e,t).map(r=>({effect:r.effectType,fn:r.effectFunction,signal:h.get(r.effectFunction)}))}function Me(e){if(!e.get&&!e.set)throw new Error('simply.state: addTracer: missing "get" or "set" property in tracer',e);if(e.get&&typeof e.get!="function")throw new Error('simply.state: addTracer: "get" is not a function',e);if(e.set&&typeof e.set!="function")throw new Error('simply.state: addTracer: "set" is not a function',e);z.push(e)}function ee(e,...t){for(let n of z)n[e]&&n[e](...t)}var q=new Set,k=0;function g(e,t={}){let n=[];if(t.forEach((r,i)=>{let s=ne(e,i);if(s?.length){for(let o of s)Le(o,y(i,r));n=n.concat(s)}}),n=new Set(n.filter(Boolean)),n)if(k)q=q.union(n);else{let r=d[d.length-1];for(let i of Array.from(n))i!=r&&i?.needsUpdate&&(I&&z.length&&ee("set",e,t,i),i()),te(i)}}function y(e,t){let n=new Map;if(typeof e=="object")for(let r in e)n.set(r,e[r]);else n.set(e,t);return n}function Le(e,t){e.context?t.forEach((n,r)=>{e.context.set(r,n)}):e.context=t,e.needsUpdate=!0}function te(e){delete e.context,delete e.needsUpdate}function v(e,t){let n=d[d.length-1];n&&(I&&z.length&&ee("get",e,t),Oe(e,t,n))}var L=new WeakMap,H=new WeakMap;function ne(e,t){let n=L.get(e);return n?Array.from(n.get(t)||[]):[]}function Oe(e,t,n){L.has(e)||L.set(e,new Map);let r=L.get(e);r.has(t)||r.set(t,new Set),r.get(t).add(n),H.has(n)||H.set(n,new Map);let i=H.get(n);i.has(t)||i.set(t,new Set),i.get(t).add(e)}function $(e){let t=H.get(e);t&&t.forEach(n=>{n.forEach(r=>{let i=L.get(r);i.has(n)&&i.get(n).delete(e)})})}var d=[],R=[],D=new WeakMap,E=[];function re(e){if(R.findIndex(r=>e==r)!==-1)throw new Error("Recursive update() call",{cause:e});R.push(e);let t=h.get(e);t||(t=A({current:null}),h.set(e,t));let n=function r(){if(E.findIndex(s=>s==t)!==-1)throw new Error("Cyclical dependency in update() call",{cause:e});$(r),r.effectFunction=e,r.effectType=re,d.push(r),E.push(t);let i;try{i=e(r,d,E)}finally{d.pop(),E.pop(),i instanceof Promise?i.then(s=>{t.current=s}):t.current=i}};return n.fn=e,D.set(t,n),n(),t}function K(e){let t=D.get(e)?.deref();if(!t)return;$(t);let n=t.fn;h.remove(n),D.delete(e)}function T(e){k++;let t;try{t=e()}finally{t instanceof Promise?t.then(()=>{k--,k||x()}):(k--,k||x())}return t}function x(){let e=Array.from(q);q=new Set;let t=d[d.length-1];for(let n of e)n!=t&&n?.needsUpdate&&n(),te(n)}function b(e,t){if(R.findIndex(o=>e==o)!==-1)throw new Error("Recursive update() call",{cause:e});R.push(e);let n=h.get(e);n||(n=A({current:null}),h.set(e,n));let r=!1,i=!0;return function o(){if(E.findIndex(c=>c==n)!==-1)throw new Error("Cyclical dependency in update() call",{cause:e});if(r&&r>Date.now()){i=!0;return}$(o),o.effectFunction=e,o.effectType=b,d.push(o),E.push(n);let l;try{l=e(o,d,E)}finally{i=!1,d.pop(),E.pop(),l instanceof Promise?l.then(c=>{n.current=c}):n.current=l}r=Date.now()+t,globalThis.setTimeout(()=>{i&&o()},t)}(),n}function ie(e,t){let n=h.get(e);n||(n=A({current:null}),h.set(e,n));let r=-1,i=!0;return function o(){if(r<t.time)if(i){$(o),o.effectFunction=e,o.effectType=ie,d.push(o),r=t.time;let l;try{l=e(o,d)}finally{d.pop(),l instanceof Promise?l.then(c=>{n.current=c}):n.current=l,i=!1}}else r=t.time;else i=!0}(),n}function V(e){let t=d.length-1,n=d[t];d[t]=!1;try{return e()}finally{d[t]=n}}function Ce(e,t=!1){let n=new Map,r=function(i){if(n.has(i))return n.get(i);switch(typeof i){case"object":if(!i)return i;if(Array.isArray(i)){let s=[];if(!t)return s=i.slice(),n.set(i,s),s;n.set(i,s);for(let o of i)s[o]=r(i[o])}else if(!i.constructor||i.constructor===Object){let s={};i.constructor||(s=Object.create(null)),n.set(i,s);for(let o in i)s[o]=t?r(i[o]):i[o];return s}else return i;break;default:return null}};return r(e)}function se(e,t){let n=e.value?.innerHTML;typeof e.value=="string"&&(n=e.value,e.value={innerHTML:n}),n&&(n=n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;"),e.value.innerHTML=n),t(e)}function oe(e,t){typeof e.value=="string"?e.value={}:delete e.value?.innerHTML,t(e)}var G={};W(G,{signal:()=>F});var je={get:(e,t,n)=>{if(t===Symbol.xRay)return e;if(t===Symbol.Signal)return!0;let r=e?.[t];return v(n,t),typeof r=="function"?r.bind(e):r&&typeof r=="object"?A(r):r},has:(e,t)=>{let n=h.get(e);return n&&v(n,t),Object.hasOwn(e,t)},ownKeys:e=>{let t=h.get(e);return t&&v(t,iterate),Reflect.ownKeys(e)}};function F(e,t){return e[Symbol.xRay]?e:(h.has(e)||(h.set(e,new Proxy(e,je)),Be(e,h.get(e),t)),h.get(e))}var le=new WeakMap;function Be(e,t,n){n||(n={characterData:!0,subtree:!0,attributes:!0,attributesOldValue:!0});let i=e.innerHTML,s=e.innerText;if(!le.has(e)){let o=new MutationObserver((l,c)=>{let a={};for(let u of l)u.type==="attributes"?a[u.attributeName]=u.attributeOldValue:u.type==="subtree"||u.type==="characterData"?(e.innerHTML!=i&&(a.innerHTML=i,i=e.innerHTML),e.innerText!=s&&(a.innerText=s,s=e.innerText)):u.type==="childList"?(a.children={was:Array.from(e.children)},a.length=-1):console.log("nothing to do for",e,u.type);for(let u in a)g(t,y(u,{was:a[u],now:e[u]}))});if(o.observe(e,n),le.set(e,o),e.matches("input, textarea, select")){let l=e.value;e.addEventListener("change",c=>{g(t,y("value",{was:l,now:e.value})),l=e.value}),e.matches("input, textarea")&&e.addEventListener("input",c=>{g(t,y("value",{was:l,now:e.value})),l=e.value})}}}function ue(e){if(e.templates?.length)Ie.call(this,e);else if(Object.hasOwnProperty.call(this.options.renderers,e.element.tagName)){let t=this.options.renderers[e.element.tagName];t&&t.call(this,e)}else this.options.renderers["*"]&&this.options.renderers["*"].call(this,e);return e}function ce(e){Array.isArray(e.value)||(e.value=[e.value]);let t=e.value.length;return e.templates?.length?Ne.call(this,e):console.error("No templates found in",e.element),e}function pe(e){return typeof e.value!="object"||!e.value?console.error("Value is not an object.",e.element,e.path,e.value):e.templates?.length?He.call(this,e):console.error("No templates found in",e.element),e}function Pe(e){if(parseInt(e)==e)return!0}function he(e,t,n){T(()=>{let r=t.split("."),i=e,s;s=r.shift();let o=null,l=null,c=i;for(;s&&i;){if(c=i,s=decodeURIComponent(s),!(s=="0"&&!Array.isArray(i))){if(s==":key")throw new Error("setting key not yet supported");s==":value"||(Array.isArray(i)&&!Pe(s)&&typeof i[s]>"u"?(o=i[0],i=i[0][s]):(o=i,i=i[s]))}if(l=s,s=r.shift(),s&&!i){let a=parseInt(s);a>=0&&s===""+a?c[l]=[]:c[l]={},i=c[l]}}if(o&&l&&o[l]!==n)if(n&&typeof n=="object"){i=o[l],i||(o[l]={},i=o[l]);for(let a in n)i[a]!==n[a]&&(i[a]=n[a])}else o[l]=n})}function Ne(e){let t=this.options.attribute,n=e.element.querySelectorAll(":scope > ["+t+"-key]"),r=0,i=0;e.list=e.value;for(let o of n){let l=parseInt(o.getAttribute(t+"-key"));if(l>r)e.index=r,e.element.insertBefore(this.applyTemplate(e),o);else if(l<r)o.remove();else{let c=Array.from(o.querySelectorAll(`[${t}]`));o.matches(`[${t}]`)&&c.unshift(o);let a=c.find(u=>{let w=u.getAttribute(t);return w.substr(0,5)!==":root"&&w.substr(0,e.path.length)!==e.path});if(!a&&o[Symbol.bindTemplate]){let u=this.findTemplate(e.templates,e.list[r]);u!=o[Symbol.bindTemplate]&&(a=!0,u||i++)}a&&(e.index=r,e.element.replaceChild(this.applyTemplate(e),o))}if(r++,r>=e.value.length)break}n=e.element.querySelectorAll(":scope > ["+t+"-key]");let s=n.length+i;if(s>e.value.length)for(;s>e.value.length;)e.element.querySelectorAll(":scope > :not(template)")?.[s-1]?.remove(),s--;else if(s<e.value.length)for(;s<e.value.length;)e.index=s,e.element.appendChild(this.applyTemplate(e)),s++;if(this.options.twoway){let o=F(e.element,{childList:!0});b(()=>{let l=Array.from(o.children);T(()=>{V(()=>{let c=0,a=e.value.slice();for(let u of l)u.tagName!=="TEMPLATE"&&u.dataset.flowKey&&(u.dataset.flowKey!=c&&he(this.options.root,e.path+"."+c,a[u.dataset.flowKey]),c++);if(e.value.length>c){let u=B(this.options.root,e.path);u.length=c}})})})}}function He(e){let t=this.options.attribute;e.list=e.value;let n=Array.from(e.element.querySelectorAll(":scope > ["+t+"-key]"));for(let r in e.list){e.index=r;let i=n.shift();if(!i){let o=this.applyTemplate(e);e.element.appendChild(o);continue}if(i.getAttribute(t+"-key")!=r){n.unshift(i);let o=e.element.querySelector(":scope > ["+t+'-key="'+r+'"]');if(o)e.element.insertBefore(o,i),i=o,n=n.filter(l=>l!=o);else{let l=this.applyTemplate(e);e.element.insertBefore(l,i);continue}}if(this.findTemplate(e.templates,e.list[e.index])!=i[Symbol.bindTemplate]){let o=this.applyTemplate(e);e.element.replaceChild(o,i)}}for(;n.length;)n.shift().remove()}function Ie(e){let t=e.element.querySelector(":scope > :not(template)"),n=this.findTemplate(e.templates,e.value);if(e.parent=qe(e.element),t)if(n){if(t?.[Symbol.bindTemplate]!=n){let r=this.applyTemplate(e);e.element.replaceChild(r,t)}}else e.element.removeChild(t);else if(n){let r=this.applyTemplate(e);e.element.appendChild(r)}}function qe(e,t){let n=e.parentElement?.closest(`[${t}-list],[${t}-map]`);return n?n.hasAttribute(`${t}-list`)?n.getAttribute(`${t}-list`)+".":n.getAttribute(`${t}-map`)+".":""}function de(e){let t=e.element,n=e.value;O.call(this,e),typeof n>"u"&&(n=""),t.type=="checkbox"||t.type=="radio"?U(t.value,n)?t.checked=!0:t.checked=!1:U(t.value,n)||(t.value=""+n)}function me(e){O.call(this,e,"value")}function J(e){let t=e.element,n=e.value;if(n===null&&(n=""),typeof n!="object")if(t.multiple){if(Array.isArray(n))for(let r of t.options)n.indexOf(r.value)===!1?r.selected=!1:r.selected=!0}else{let r=t.options.find(i=>U(i.value,n));r&&(r.selected=!0,r.setAttribute("selected",!0))}else n.options&&Re(t,n.options),n.selected&&J(Object.asssign({},e,{value:n.selected})),j(t,n,"name","id","selectedIndex","className")}function ae(e,t){t&&(typeof t!="object"?e.options.add(new Option(""+t)):t.text?e.options.add(new Option(t.text,t.value,t.defaultSelected,t.selected)):typeof t.value<"u"&&e.options.add(new Option(""+t.value,t.value,t.defaultSelected,t.selected)))}function Re(e,t){if(e.innerHTML="",Array.isArray(t))for(let n of t)ae(e,n);else if(t&&typeof t=="object")for(let n in t)ae(e,{text:t[n],value:n})}function ye(e){O.call(this,e,"target","href","name","newwindow","nofollow"),this.options.twoway&&T(()=>{C.call(this,e,["target","href","name","newwindow","nofollow"])})}function be(e){j(e.element,e.value,"title","alt","src","id"),this.options.twoway&&T(()=>{C.call(this,e,["title","alt","src","id"])})}function ge(e){j(e.element,e.value,"title","src","id"),this.options.twoway&&T(()=>{C.call(this,e,["title","src","id"])})}function we(e){j(e.element,e.value,"content","id"),this.options.twoway&&T(()=>{C.call(this,e,["content","id"])})}var fe=new WeakMap;function O(e,...t){let n=e.element,r=e.value,i=!1;if(typeof r<"u"&&r!==null){let o=""+r;(typeof r!="object"||o.substring(0,8)!="[object ")&&(r={innerHTML:r},i=!0)}let s=["innerHTML","title","id","className"].concat(t);j(n,r,...s),this.options.twoway&&T(()=>{C.call(this,e,s,i)})}function C(e,t,n){if(fe.has(e.element))return;let r=F(e.element);fe.set(e.element,r),b(()=>{let i=r.innerHTML;n||(i=ze(r,...t)),V(()=>{he(this.options.root,e.path,i)})})}function j(e,t,...n){if(!(!t||typeof t!="object"))for(let r of n)typeof t[r]>"u"||U(e[r],t[r])||(t[r]===null?e[r]="":e[r]=""+t[r])}function ze(e,...t){let n={};for(let r of t)switch(r){default:n[r]=e[r];break}return n}function U(e,t){return e==":empty"&&!t||t==":empty"&&!e||""+e==""+t}Symbol.bindTemplate||(Symbol.bindTemplate=Symbol("bindTemplate"));var Q=class{constructor(t){this.bindings=new Map;let n={escape_html:se,fixed_content:oe},r={container:document.body,attribute:"data-flow",transformers:n,render:{field:[ue],list:[ce],map:[pe]},renderers:{INPUT:de,BUTTON:me,SELECT:J,A:ye,IMG:be,IFRAME:ge,META:we,TEMPLATE:null,"*":O},twoway:!1};if(!t?.root)throw new Error("bind needs at least options.root set");this.options=Object.assign({},r,t),t.transformers&&(this.options.transformers=Object.assign({},n,t?.transformers));let i=this.options.attribute,s=[i+"-field",i+"-list",i+"-map"],o=i+"-transform",l=f=>{let p=s.find(m=>f.hasAttribute(m));return p||console.error("No matching attribute found",f,s),p},c=f=>{this.bindings.set(f,b(()=>{if(!f.isConnected){Ve(f,this.getBindingPath(f)),K(this.bindings.get(f));return}let p={templates:f.querySelectorAll(":scope > template"),attribute:l(f)};p.path=this.getBindingPath(f),p.value=B(this.options.root,p.path),p.element=f,Ke(f,p),a(p)},50))},a=f=>{let p;switch(f.attribute){case this.options.attribute+"-field":p=Array.from(this.options.render.field);break;case this.options.attribute+"-list":p=Array.from(this.options.render.list);break;case this.options.attribute+"-map":p=Array.from(this.options.render.map);break;default:throw new Error("no valid context attribute specified",f)}f.element.hasAttribute(o)&&f.element.getAttribute(o).split(" ").filter(Boolean).forEach(S=>{this.options.transformers[S]?p.push(this.options.transformers[S]):console.warn("No transformer with name "+S+" configured",{cause:f.element})});let m;for(let S of p)m=((M,Te)=>Ae=>Te.call(this,Ae,M))(m,S);m(f)},u=f=>{for(let p of f)this.bindings.get(p)||c(p)},w=f=>{let p=`[${i}-field],[${i}-list],[${i}-map]`;for(let m of f)if(m.type=="childList"&&m.addedNodes){for(let S of m.addedNodes)if(S instanceof HTMLElement){let M=Array.from(S.querySelectorAll(p));S.matches(p)&&M.unshift(S),M.length&&u(M)}}};this.observer=new MutationObserver(f=>{w(f)}),this.observer.observe(this.options.container,{subtree:!0,childList:!0});let N=this.options.container.querySelectorAll(":is(["+this.options.attribute+"-field],["+this.options.attribute+"-list],["+this.options.attribute+"-map]):not(template)");N.length&&u(N)}applyTemplate(t){let n=t.path,r=t.parent,i=t.templates,s=t.list,o=t.index,l=s?s[o]:t.value,c=this.findTemplate(i,l);if(!c){let f=new DocumentFragment;return f.innerHTML="<!-- no matching template -->",f}let a=c.content.cloneNode(!0);if(!a.children?.length)return a;if(a.children.length>1)throw new Error("template must contain a single root node",{cause:c});let u=this.options.attribute,w=[u+"-field",u+"-list",u+"-map"],N=a.querySelectorAll(`[${u}-field],[${u}-list],[${u}-map]`);for(let f of N){if(f.tagName=="TEMPLATE")continue;let p=w.find(S=>f.hasAttribute(S)),m=f.getAttribute(p);m=this.applyLinks(c.links,m),m.substring(0,6)==":root."?f.setAttribute(p,m.substring(6)):m==":value"&&o!=null?f.setAttribute(p,n+"."+o):o!=null?f.setAttribute(p,n+"."+o+"."+m):f.setAttribute(p,r+m)}return typeof o<"u"&&a.children[0].setAttribute(u+"-key",o),a.children[0][Symbol.bindTemplate]=c,a}parseLinks(t){let n={};t=t.split(";").map(r=>r.trim());for(let r of t)r=r.split("="),n[r[0].trim()]=r[1].trim();return n}applyLinks(t,n){for(let r in t){if(n.startsWith(r+"."))return t[r]+n.substr(r.length);if(n==r)return t[r]}return n}getBindingPath(t){let n=[this.options.attribute+"-field",this.options.attribute+"-list",this.options.attribute+"-map"];for(let r of n)if(t.hasAttribute(r))return t.getAttribute(r)}findTemplate(t,n){let r=l=>{let c=this.getBindingPath(l),a;c?c.substr(0,6)==":root."?a=B(this.options.root,c):a=B(n,c):a=n;let u=""+a,w=l.getAttribute(this.options.attribute+"-match");if(w){if(w===":empty"&&!a)return l;if(w===":notempty"&&a||u==w)return l}if(!w)return l},i=Array.from(t).find(r),s=null;i?.hasAttribute(this.options.attribute+"-link")&&(s=this.parseLinks(i.getAttribute(this.options.attribute+"-link")));let o=i?.getAttribute("rel");if(o){let l=document.querySelector("template#"+o);if(!l)throw new Error("Could not find template with id "+o);i=l}return i&&(i.links=s),i}destroy(){this.bindings.forEach(t=>{K(t)}),this.bindings=new Map,this.observer.disconnect()}};function Se(e){return new Q(e)}var P=new Map;function Ke(e,t){P.has(t.path)?P.get(t.path).push(t):P.set(t.path,[t])}function Ve(e,t){let n=P.get(t);n&&(n=n.filter(r=>r.element==e),P.set(t,n))}function B(e,t){let n=t.split("."),r=e,i;i=n.shift();let s=null;for(;i&&r;)i=decodeURIComponent(i),i=="0"&&!Array.isArray(r)||(i==":key"?r=s:i==":value"||(Array.isArray(r)&&typeof r[i]>"u"&&r[0]?r=r[0][i]:r=r[i])),s=i,i=n.shift();return r}var Y={};W(Y,{columns:()=>_e,filter:()=>De,model:()=>Fe,paging:()=>We,scroll:()=>Ge,sort:()=>Ue});var X=class{constructor(t){if(!t)throw new Error("no options set");(t.data==null||typeof t.data[Symbol.iterator]!="function")&&console.warn("SimplyFlowModel: options.data is not iterable"),this.state=A(t),this.state.options||(this.state.options={}),this.effects=[{current:this.state.data}],this.view={current:this.state.data}}addEffect(t){if(!t||typeof t!="function")throw new Error("addEffect requires an effect function as its parameter",{cause:t});let n=this.effects[this.effects.length-1],r=t.call(this,n);if(!r||!r[Symbol.Signal])throw new Error("addEffect function parameter must return a Signal",{cause:t});this.view=r,this.effects.push(this.view)}};function Fe(e){return new X(e)}function Ue(e={}){return function(t){return this.state.options.sort=Object.assign({direction:"asc",sortBy:null,sortFn:(n,r)=>{let i=this.state.options.sort,s=i.sortBy;if(!i.sortBy)return 0;let o=i.direction=="asc"?1:-1,l=i.direction=="asc"?-1:1;return typeof n?.[s]>"u"?typeof r?.[s]>"u"?0:o:typeof r?.[s]>"u"||n[s]<r[s]?l:n[s]>r[s]?o:0}},e),b(()=>{let n=this.state.options.sort;return n?.sortBy&&n?.direction?t.current.toSorted(n?.sortFn):t.current},50)}}function We(e={}){return function(t){return this.state.options.paging=Object.assign({page:1,pageSize:20,max:1},e),b(()=>T(()=>{let n=this.state.options.paging;n.pageSize||(n.pageSize=20),n.max=Math.ceil(this.state.data.length/n.pageSize),n.page=Math.max(1,Math.min(n.max,n.page));let r=(n.page-1)*n.pageSize,i=r+n.pageSize;return t.current.slice(r,i)}),50)}}function De(e){if(!e?.name||typeof e.name!="string")throw new Error("filter requires options.name to be a string");if(!e.matches||typeof e.matches!="function")throw new Error("filter requires options.matches to be a function");return function(t){if(this.state.options[e.name])throw new Error("a filter with this name already exists on this model");return this.state.options[e.name]=e,b(()=>this.state.options[e.name].enabled?t.current.filter(this.state.options[e.name].matches.bind(this)):t.current,50)}}function _e(e={}){if(!e||typeof e!="object"||Object.keys(e).length===0)throw new Error("columns requires options to be an object with at least one property");return function(t){return this.state.options.columns=e,b(()=>t.current.map(n=>{let r={};for(let i of Object.keys(this.state.options.columns))this.state.options.columns[i]?.hidden||(r[i]=n[i]??null);return r}),50)}}function Ge(e){return function(t){this.state.options.scroll=Object.assign({offset:0,rowHeight:26,rowCount:20,itemsPerRow:1,size:t.current.length},e);let n=this.state.options.scroll,r=n.scrollbar||n.container?.querySelector("[data-flow-scrollbar]");return r&&(n.container&&n.container.addEventListener("scroll",i=>{n.offset=Math.floor(n.container.scrollTop/(n.rowHeight*n.itemsPerRow))}),b(()=>{n.size=t.current.length*n.rowHeight,r.style.height=n.size+"px"},50)),b(()=>{n.container&&(n.rowCount=Math.ceil(n.container.getBoundingClientRect().height/n.rowHeight)),n.data=t.current;let i=Math.min(n.offset,t.current.length-1),s=i+n.rowCount;return s>t.current.length&&(s=t.current.length,i=s-n.rowCount),t.current.slice(i,s)},50)}}var Z=class extends HTMLElement{constructor(){super()}connectedCallback(){let t=this.getAttribute("rel"),n=document.getElementById(t);if(n){let r=n.content.cloneNode(!0);for(let i of r.childNodes){let s=i.cloneNode(!0);if(s.nodeType==document.ELEMENT_NODE&&(s.querySelectorAll("template").forEach(function(o){o.setAttribute("simply-render","")}),this.attributes))for(let o of this.attributes)o.name!="rel"&&s.setAttribute(o.name,o.value);this.parentNode.insertBefore(s,this)}this.parentNode.removeChild(this)}else(()=>{let i=new MutationObserver(()=>{n=document.getElementById(t),n&&(i.disconnect(),this.replaceWith(this))});i.observe(globalThis.document,{subtree:!0,childList:!0})})()}};customElements.get("simply-render")||customElements.define("simply-render",Z);globalThis.simply||(globalThis.simply={});Object.assign(globalThis.simply,{bind:Se,flow:Y,state:_,dom:G});var ft=globalThis.simply;})();
1
+ (()=>{var ke=Object.defineProperty;var D=(e,t)=>{for(var n in t)ke(e,n,{get:t[n],enumerable:!0})};var U={};D(U,{addTracer:()=>Pe,batch:()=>T,clockEffect:()=>oe,clone:()=>Ce,destroy:()=>$,effect:()=>se,makeContext:()=>y,notifyGet:()=>v,notifySet:()=>g,signal:()=>E,signals:()=>d,throttledEffect:()=>b,trace:()=>Le,untracked:()=>V});Symbol.iterate||(Symbol.iterate=Symbol("iterate"));Symbol.xRay||(Symbol.xRay=Symbol("xRay"));Symbol.Signal||(Symbol.Signal=Symbol("Signal"));var Me={get:(e,t,n)=>{if(t===Symbol.xRay)return e;if(t===Symbol.Signal)return!0;let r=e?.[t];return v(n,t),typeof r=="function"?Array.isArray(e)?(...i)=>{let s=e.length,o=r.apply(n,i);return s!=e.length&&g(n,y("length",{was:s,now:e.length})),o}:e instanceof Set||e instanceof Map?(...i)=>{let s=e.size,o=r.apply(e,i);return s!=e.size&&g(n,y("size",{was:s,now:e.size})),["set","add","clear","delete"].includes(t)&&g(n,y({entries:{},forEach:{},has:{},keys:{},values:{},[Symbol.iterator]:{}})),o}:e instanceof HTMLElement||e instanceof Number||e instanceof String||e instanceof Boolean?r.bind(e):r.bind(n):r&&typeof r=="object"?E(r):r},set:(e,t,n,r)=>{let i=e[t];return i!==n&&(e[t]=n,g(r,y(t,{was:i,now:n}))),typeof i>"u"&&(g(r,y(Symbol.iterate,{})),g(r,y("length",{}))),!0},has:(e,t)=>{let n=d.get(e);return n&&v(n,t),Object.hasOwn(e,t)},deleteProperty:(e,t)=>{if(typeof e[t]<"u"){let n=e[t];delete e[t];let r=d.get(e);g(r,y(t,{delete:!0,was:n}))}return!0},defineProperty:(e,t,n)=>{if(typeof e[t]>"u"){let r=d.get(e);g(r,y(Symbol.iterate,{}))}return Object.defineProperty(e,t,n)},ownKeys:e=>{let t=d.get(e);return v(t,Symbol.iterate),Reflect.ownKeys(e)}},d=new WeakMap;function E(e){return e||(e={}),e[Symbol.Signal]?e:(d.has(e)||d.set(e,new Proxy(e,Me)),d.get(e))}var R=[],H=!1;function Le(e,t){if(typeof e=="function")H=!0,e(),H=!1;else return ie(e,t).map(r=>({effect:r.effectType,fn:r.effectFunction,signal:d.get(r.effectFunction)}))}function Pe(e){if(!e.get&&!e.set)throw new Error('simply.state: addTracer: missing "get" or "set" property in tracer',e);if(e.get&&typeof e.get!="function")throw new Error('simply.state: addTracer: "get" is not a function',e);if(e.set&&typeof e.set!="function")throw new Error('simply.state: addTracer: "set" is not a function',e);R.push(e)}function ne(e,...t){for(let n of R)n[e]&&n[e](...t)}var I=new Set,k=0;function g(e,t={}){let n=[];if(t.forEach((r,i)=>{let s=ie(e,i);if(s?.length){for(let o of s)Oe(o,y(i,r));n=n.concat(s)}}),n=new Set(n.filter(Boolean)),n)if(k)I=I.union(n);else{let r=h[h.length-1];for(let i of Array.from(n))i!=r&&i?.needsUpdate&&(H&&R.length&&ne("set",e,t,i),i()),re(i)}}function y(e,t){let n=new Map;if(typeof e=="object")for(let r in e)n.set(r,e[r]);else n.set(e,t);return n}function Oe(e,t){e.context?t.forEach((n,r)=>{e.context.set(r,n)}):e.context=t,e.needsUpdate=!0}function re(e){delete e.context,delete e.needsUpdate}function v(e,t){let n=h[h.length-1];n&&(H&&R.length&&ne("get",e,t),Be(e,t,n))}var L=new WeakMap,N=new WeakMap;function ie(e,t){let n=L.get(e);return n?Array.from(n.get(t)||[]):[]}function Be(e,t,n){L.has(e)||L.set(e,new Map);let r=L.get(e);r.has(t)||r.set(t,new Set),r.get(t).add(n),N.has(n)||N.set(n,new Map);let i=N.get(n);i.has(t)||i.set(t,new Set),i.get(t).add(e)}function z(e){let t=N.get(e);t&&t.forEach(n=>{n.forEach(r=>{let i=L.get(r);i.has(n)&&i.get(n).delete(e)})})}var h=[],q=[],K=new WeakMap,A=[];function se(e){if(q.findIndex(r=>e==r)!==-1)throw new Error("Recursive update() call",{cause:e});q.push(e);let t=d.get(e);t||(t=E({current:null}),d.set(e,t));let n=function r(){if(A.findIndex(s=>s==t)!==-1)throw new Error("Cyclical dependency in update() call",{cause:e});z(r),r.effectFunction=e,r.effectType=se,h.push(r),A.push(t);let i;try{i=e(r,h,A)}finally{h.pop(),A.pop(),i instanceof Promise?i.then(s=>{t.current=s}):t.current=i}};return n.fn=e,K.set(t,n),n(),t}function $(e){let t=K.get(e)?.deref();if(!t)return;z(t);let n=t.fn;d.remove(n),K.delete(e)}function T(e){k++;let t;try{t=e()}finally{t instanceof Promise?t.then(()=>{k--,k||te()}):(k--,k||te())}return t}function te(){let e=Array.from(I);I=new Set;let t=h[h.length-1];for(let n of e)n!=t&&n?.needsUpdate&&n(),re(n)}function b(e,t){if(q.findIndex(o=>e==o)!==-1)throw new Error("Recursive update() call",{cause:e});q.push(e);let n=d.get(e);n||(n=E({current:null}),d.set(e,n));let r=!1,i=!0;return function o(){if(A.findIndex(u=>u==n)!==-1)throw new Error("Cyclical dependency in update() call",{cause:e});if(r&&r>Date.now()){i=!0;return}z(o),o.effectFunction=e,o.effectType=b,h.push(o),A.push(n);let l;try{l=e(o,h,A)}finally{i=!1,h.pop(),A.pop(),l instanceof Promise?l.then(u=>{n.current=u}):n.current=l}r=Date.now()+t,globalThis.setTimeout(()=>{i&&o()},t)}(),n}function oe(e,t){let n=d.get(e);n||(n=E({current:null}),d.set(e,n));let r=-1,i=!0;return function o(){if(r<t.time)if(i){z(o),o.effectFunction=e,o.effectType=oe,h.push(o),r=t.time;let l;try{l=e(o,h)}finally{h.pop(),l instanceof Promise?l.then(u=>{n.current=u}):n.current=l,i=!1}}else r=t.time;else i=!0}(),n}function V(e){let t=h.length-1,n=h[t];h[t]=!1;try{return e()}finally{h[t]=n}}function Ce(e,t=!1){let n=new Map,r=function(i){if(n.has(i))return n.get(i);switch(typeof i){case"object":if(!i)return i;if(Array.isArray(i)){let s=[];if(!t)return s=i.slice(),n.set(i,s),s;n.set(i,s);for(let o of i)s[o]=r(i[o])}else if(!i.constructor||i.constructor===Object){let s={};i.constructor||(s=Object.create(null)),n.set(i,s);for(let o in i)s[o]=t?r(i[o]):i[o];return s}else return i;break;default:return null}};return r(e)}function le(e,t){let n=e.value?.innerHTML;typeof e.value=="string"&&(n=e.value,e.value={innerHTML:n}),n&&(n=n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;"),e.value.innerHTML=n),t(e)}function ae(e,t){typeof e.value=="string"?e.value={}:delete e.value?.innerHTML,t(e)}var J={};D(J,{signal:()=>W,trackDomField:()=>G,trackDomList:()=>_});var fe=new WeakMap,je={get:(e,t,n)=>{if(t===Symbol.xRay)return e;if(t===Symbol.Signal)return!0;let r=e?.[t];return v(n,t),typeof r=="function"?r.bind(e):r&&typeof r=="object"?E(r):r},has:(e,t)=>{let n=d.get(e);return n&&v(n,t),Object.hasOwn(e,t)},ownKeys:e=>{let t=d.get(e);return t&&v(t,iterate),Reflect.ownKeys(e)}};function W(e,t){return e[Symbol.xRay]?e:(d.has(e)||(d.set(e,new Proxy(e,je)),Ne(e,d.get(e),t)),d.get(e))}var ue=new WeakMap;function Ne(e,t,n){n||(n={characterData:!0,subtree:!0,attributes:!0,attributesOldValue:!0});let i=e.innerHTML,s=e.innerText;if(!ue.has(e)){let o=new MutationObserver((l,u)=>{let f={};for(let c of l)c.type==="attributes"?f[c.attributeName]=c.attributeOldValue:c.type==="subtree"||c.type==="characterData"?(e.innerHTML!=i&&(f.innerHTML=i,i=e.innerHTML),e.innerText!=s&&(f.innerText=s,s=e.innerText)):c.type==="childList"?(f.children={was:Array.from(e.children)},f.length=-1):console.log("nothing to do for",e,c.type);for(let c in f)g(t,y(c,{was:f[c],now:e[c]}))});if(o.observe(e,n),ue.set(e,o),e.matches("input, textarea, select")){let l=e.value;e.addEventListener("change",u=>{g(t,y("value",{was:l,now:e.value})),l=e.value}),e.matches("input, textarea")&&e.addEventListener("input",u=>{g(t,y("value",{was:l,now:e.value})),l=e.value})}}}function _(e){let t=this.getBindingPath(e);if(!t)throw new Error("Could not find binding path for element",{cause:e});let n=W(e,{childList:!0});b(()=>{let r=Array.from(n.children);V(()=>{T(()=>{let i=0,s=P(this.options.root,t),o=s.slice();for(let l of r)l.tagName!=="TEMPLATE"&&l.dataset.flowKey&&(l.dataset.flowKey!=i&&Q(this.options.root,t+"."+i,o[l.dataset.flowKey]),i++);s.length>i&&(s.length=i)})})})}function G(e,t,n){if(fe.has(e))return;let r=this.getBindingPath(e);if(!r)throw new Error("Could not find binding path for element",{cause:e});let i=W(e);fe.set(e,i),T(()=>{b(()=>{let s=i.innerHTML;n||(s=ce(i,...t)),V(()=>{Q(this.options.root,r,s)})})})}function de(e){if(e.templates?.length)Re.call(this,e);else if(Object.hasOwnProperty.call(this.options.renderers,e.element.tagName)){let t=this.options.renderers[e.element.tagName];t&&t.call(this,e)}else this.options.renderers["*"]&&this.options.renderers["*"].call(this,e);return e}function he(e){Array.isArray(e.value)||(e.value=[e.value]);let t=e.value.length;return e.templates?.length?Ie.call(this,e):console.error("No templates found in",e.element),e}function me(e){return typeof e.value!="object"||!e.value?console.error("Value is not an object.",e.element,e.path,e.value):e.templates?.length?qe.call(this,e):console.error("No templates found in",e.element),e}function He(e){if(parseInt(e)==e)return!0}function Q(e,t,n){T(()=>{let r=t.split("."),i=e,s;s=r.shift();let o=null,l=null,u=i;for(;s&&i;){if(u=i,s=decodeURIComponent(s),!(s=="0"&&!Array.isArray(i))){if(s==":key")throw new Error("setting key not yet supported");s==":value"||(Array.isArray(i)&&!He(s)&&typeof i[s]>"u"?(o=i[0],i=i[0][s]):(o=i,i=i[s]))}if(l=s,s=r.shift(),s&&!i){let f=parseInt(s);f>=0&&s===""+f?u[l]=[]:u[l]={},i=u[l]}}if(o&&l&&o[l]!==n)if(n&&typeof n=="object"){i=o[l],i||(o[l]={},i=o[l]);for(let f in n)i[f]!==n[f]&&(i[f]=n[f])}else o[l]=n})}function Ie(e){let t=this.options.attribute,n=e.element.querySelectorAll(":scope > ["+t+"-key]"),r=0,i=0;e.list=e.value;for(let o of n){let l=parseInt(o.getAttribute(t+"-key"));if(l>r)e.index=r,e.element.insertBefore(this.applyTemplate(e),o);else if(l<r)o.remove();else{let u=Array.from(o.querySelectorAll(`[${t}]`));o.matches(`[${t}]`)&&u.unshift(o);let f=u.find(c=>{let w=c.getAttribute(t);return w.substr(0,5)!==":root"&&w.substr(0,e.path.length)!==e.path});if(!f&&o[Symbol.bindTemplate]){let c=this.findTemplate(e.templates,e.list[r]);c!=o[Symbol.bindTemplate]&&(f=!0,c||i++)}f&&(e.index=r,e.element.replaceChild(this.applyTemplate(e),o))}if(r++,r>=e.value.length)break}n=e.element.querySelectorAll(":scope > ["+t+"-key]");let s=n.length+i;if(s>e.value.length)for(;s>e.value.length;)e.element.querySelectorAll(":scope > :not(template)")?.[s-1]?.remove(),s--;else if(s<e.value.length)for(;s<e.value.length;)e.index=s,e.element.appendChild(this.applyTemplate(e)),s++;this.options.twoway&&_.call(this,e.element)}function qe(e){let t=this.options.attribute;e.list=e.value;let n=Array.from(e.element.querySelectorAll(":scope > ["+t+"-key]"));for(let r in e.list){e.index=r;let i=n.shift();if(!i){let o=this.applyTemplate(e);e.element.appendChild(o);continue}if(i.getAttribute(t+"-key")!=r){n.unshift(i);let o=e.element.querySelector(":scope > ["+t+'-key="'+r+'"]');if(o)e.element.insertBefore(o,i),i=o,n=n.filter(l=>l!=o);else{let l=this.applyTemplate(e);e.element.insertBefore(l,i);continue}}if(this.findTemplate(e.templates,e.list[e.index])!=i[Symbol.bindTemplate]){let o=this.applyTemplate(e);e.element.replaceChild(o,i)}}for(;n.length;)n.shift().remove()}function Re(e){let t=e.element.querySelector(":scope > :not(template)"),n=this.findTemplate(e.templates,e.value);if(e.parent=ze(e.element),t)if(n){if(t?.[Symbol.bindTemplate]!=n){let r=this.applyTemplate(e);e.element.replaceChild(r,t)}}else e.element.removeChild(t);else if(n){let r=this.applyTemplate(e);e.element.appendChild(r)}}function ze(e,t){let n=e.parentElement?.closest(`[${t}-list],[${t}-map]`);return n?n.hasAttribute(`${t}-list`)?n.getAttribute(`${t}-list`)+".":n.getAttribute(`${t}-map`)+".":""}function ye(e){let t=e.element,n=e.value;O.call(this,e),typeof n>"u"&&(n=""),t.type=="checkbox"||t.type=="radio"?F(t.value,n)?t.checked=!0:t.checked=!1:F(t.value,n)||(t.value=""+n)}function be(e){O.call(this,e,"value")}function X(e){let t=e.element,n=e.value;if(n===null&&(n=""),typeof n!="object")if(t.multiple){if(Array.isArray(n))for(let r of t.options)n.indexOf(r.value)===!1?r.selected=!1:r.selected=!0}else{let r=t.options.find(i=>F(i.value,n));r&&(r.selected=!0,r.setAttribute("selected",!0))}else n.options&&$e(t,n.options),n.selected&&X(Object.asssign({},e,{value:n.selected})),B(t,n,"name","id","selectedIndex","className")}function pe(e,t){t&&(typeof t!="object"?e.options.add(new Option(""+t)):t.text?e.options.add(new Option(t.text,t.value,t.defaultSelected,t.selected)):typeof t.value<"u"&&e.options.add(new Option(""+t.value,t.value,t.defaultSelected,t.selected)))}function $e(e,t){if(e.innerHTML="",Array.isArray(t))for(let n of t)pe(e,n);else if(t&&typeof t=="object")for(let n in t)pe(e,{text:t[n],value:n})}function ge(e){O.call(this,e,"target","href","name","newwindow","nofollow"),this.options.twoway&&T(()=>{updateProperties.call(this,e,["target","href","name","newwindow","nofollow"])})}function we(e){B(e.element,e.value,"title","alt","src","id"),this.options.twoway&&T(()=>{updateProperties.call(this,e,["title","alt","src","id"])})}function Se(e){B(e.element,e.value,"title","src","id"),this.options.twoway&&T(()=>{updateProperties.call(this,e,["title","src","id"])})}function Te(e){B(e.element,e.value,"content","id"),this.options.twoway&&T(()=>{updateProperties.call(this,e,["content","id"])})}function O(e,...t){let n=e.element,r=e.value,i=!1;if(typeof r<"u"&&r!==null){let o=""+r;(typeof r!="object"||o.substring(0,8)!="[object ")&&(r={innerHTML:r},i=!0)}let s=["innerHTML","title","id","className"].concat(t);B(n,r,...s),this.options.twoway&&G.call(this,e.element,s,i)}function B(e,t,...n){if(!(!t||typeof t!="object"))for(let r of n)typeof t[r]>"u"||F(e[r],t[r])||(t[r]===null?e[r]="":e[r]=""+t[r])}function ce(e,...t){let n={};for(let r of t)switch(r){default:n[r]=e[r];break}return n}function F(e,t){return e==":empty"&&!t||t==":empty"&&!e||""+e==""+t}Symbol.bindTemplate||(Symbol.bindTemplate=Symbol("bindTemplate"));var Y=class{constructor(t){this.bindings=new Map;let n={escape_html:le,fixed_content:ae},r={container:document.body,attribute:"data-flow",transformers:n,render:{field:[de],list:[he],map:[me]},renderers:{INPUT:ye,BUTTON:be,SELECT:X,A:ge,IMG:we,IFRAME:Se,META:Te,TEMPLATE:null,"*":O},twoway:!1};if(!t?.root)throw new Error("bind needs at least options.root set");this.options=Object.assign({},r,t),t.transformers&&(this.options.transformers=Object.assign({},n,t?.transformers));let i=this.options.attribute,s=[i+"-field",i+"-list",i+"-map"],o=i+"-transform",l=a=>{let p=s.find(m=>a.hasAttribute(m));return p||console.error("No matching attribute found",a,s),p},u=a=>{this.bindings.set(a,b(()=>{if(!a.isConnected){De(a,this.getBindingPath(a)),$(this.bindings.get(a));return}let p={templates:a.querySelectorAll(":scope > template"),attribute:l(a)};p.path=this.getBindingPath(a),p.value=P(this.options.root,p.path),p.element=a,Fe(a,p),f(p)},50))},f=a=>{let p;switch(a.attribute){case this.options.attribute+"-field":p=Array.from(this.options.render.field);break;case this.options.attribute+"-list":p=Array.from(this.options.render.list);break;case this.options.attribute+"-map":p=Array.from(this.options.render.map);break;default:throw new Error("no valid context attribute specified",a)}a.element.hasAttribute(o)&&a.element.getAttribute(o).split(" ").filter(Boolean).forEach(S=>{this.options.transformers[S]?p.push(this.options.transformers[S]):console.warn("No transformer with name "+S+" configured",{cause:a.element})});let m;for(let S of p)m=((M,Ae)=>ve=>Ae.call(this,ve,M))(m,S);m(a)},c=a=>{for(let p of a)this.bindings.get(p)||u(p)},w=a=>{let p=`[${i}-field],[${i}-list],[${i}-map]`;for(let m of a)if(m.type=="childList"&&m.addedNodes){for(let S of m.addedNodes)if(S instanceof HTMLElement){let M=Array.from(S.querySelectorAll(p));S.matches(p)&&M.unshift(S),M.length&&c(M)}}};this.observer=new MutationObserver(a=>{w(a)}),this.observer.observe(this.options.container,{subtree:!0,childList:!0});let j=this.options.container.querySelectorAll(":is(["+this.options.attribute+"-field],["+this.options.attribute+"-list],["+this.options.attribute+"-map]):not(template)");j.length&&c(j)}applyTemplate(t){let n=t.path,r=t.parent,i=t.templates,s=t.list,o=t.index,l=s?s[o]:t.value,u=this.findTemplate(i,l);if(!u){let a=new DocumentFragment;return a.innerHTML="<!-- no matching template -->",a}let f=u.content.cloneNode(!0);if(!f.children?.length)return f;if(f.children.length>1)throw new Error("template must contain a single root node",{cause:u});let c=this.options.attribute,w=[c+"-field",c+"-list",c+"-map"],j=f.querySelectorAll(`[${c}-field],[${c}-list],[${c}-map]`);for(let a of j){if(a.tagName=="TEMPLATE")continue;let p=w.find(S=>a.hasAttribute(S)),m=a.getAttribute(p);m=this.applyLinks(u.links,m),m.substring(0,6)==":root."?a.setAttribute(p,m.substring(6)):m==":value"&&o!=null?a.setAttribute(p,n+"."+o):o!=null?a.setAttribute(p,n+"."+o+"."+m):a.setAttribute(p,r+m)}return typeof o<"u"&&f.children[0].setAttribute(c+"-key",o),f.children[0][Symbol.bindTemplate]=u,f}parseLinks(t){let n={};t=t.split(";").map(r=>r.trim());for(let r of t)r=r.split("="),n[r[0].trim()]=r[1].trim();return n}applyLinks(t,n){for(let r in t){if(n.startsWith(r+"."))return t[r]+n.substr(r.length);if(n==r)return t[r]}return n}getBindingPath(t){let n=[this.options.attribute+"-field",this.options.attribute+"-list",this.options.attribute+"-map"];for(let r of n)if(t.hasAttribute(r))return t.getAttribute(r)}findTemplate(t,n){let r=l=>{let u=this.getBindingPath(l),f;u?u.substr(0,6)==":root."?f=P(this.options.root,u):f=P(n,u):f=n;let c=""+f,w=l.getAttribute(this.options.attribute+"-match");if(w){if(w===":empty"&&!f)return l;if(w===":notempty"&&f||c==w)return l}if(!w)return l},i=Array.from(t).find(r),s=null;i?.hasAttribute(this.options.attribute+"-link")&&(s=this.parseLinks(i.getAttribute(this.options.attribute+"-link")));let o=i?.getAttribute("rel");if(o){let l=document.querySelector("template#"+o);if(!l)throw new Error("Could not find template with id "+o);i=l}return i&&(i.links=s),i}destroy(){this.bindings.forEach(t=>{$(t)}),this.bindings=new Map,this.observer.disconnect()}};function Ee(e){return new Y(e)}var C=new Map;function Fe(e,t){C.has(t.path)?C.get(t.path).push(t):C.set(t.path,[t])}function De(e,t){let n=C.get(t);n&&(n=n.filter(r=>r.element==e),C.set(t,n))}function P(e,t){let n=t.split("."),r=e,i;i=n.shift();let s=null;for(;i&&r;)i=decodeURIComponent(i),i=="0"&&!Array.isArray(r)||(i==":key"?r=s:i==":value"||(Array.isArray(r)&&typeof r[i]>"u"&&r[0]?r=r[0][i]:r=r[i])),s=i,i=n.shift();return r}var x={};D(x,{columns:()=>Ge,filter:()=>_e,model:()=>Ke,paging:()=>We,scroll:()=>Je,sort:()=>Ue});var Z=class{constructor(t){if(!t)throw new Error("no options set");(t.data==null||typeof t.data[Symbol.iterator]!="function")&&console.warn("SimplyFlowModel: options.data is not iterable"),this.state=E(t),this.state.options||(this.state.options={}),this.effects=[{current:this.state.data}],this.view={current:this.state.data}}addEffect(t){if(!t||typeof t!="function")throw new Error("addEffect requires an effect function as its parameter",{cause:t});let n=this.effects[this.effects.length-1],r=t.call(this,n);if(!r||!r[Symbol.Signal])throw new Error("addEffect function parameter must return a Signal",{cause:t});this.view=r,this.effects.push(this.view)}};function Ke(e){return new Z(e)}function Ue(e={}){return function(t){return this.state.options.sort=Object.assign({direction:"asc",sortBy:null,sortFn:(n,r)=>{let i=this.state.options.sort,s=i.sortBy;if(!i.sortBy)return 0;let o=i.direction=="asc"?1:-1,l=i.direction=="asc"?-1:1;return typeof n?.[s]>"u"?typeof r?.[s]>"u"?0:o:typeof r?.[s]>"u"||n[s]<r[s]?l:n[s]>r[s]?o:0}},e),b(()=>{let n=this.state.options.sort;return n?.sortBy&&n?.direction?t.current.toSorted(n?.sortFn):t.current},50)}}function We(e={}){return function(t){return this.state.options.paging=Object.assign({page:1,pageSize:20,max:1},e),b(()=>T(()=>{let n=this.state.options.paging;n.pageSize||(n.pageSize=20),n.max=Math.ceil(this.state.data.length/n.pageSize),n.page=Math.max(1,Math.min(n.max,n.page));let r=(n.page-1)*n.pageSize,i=r+n.pageSize;return t.current.slice(r,i)}),50)}}function _e(e){if(!e?.name||typeof e.name!="string")throw new Error("filter requires options.name to be a string");if(!e.matches||typeof e.matches!="function")throw new Error("filter requires options.matches to be a function");return function(t){if(this.state.options[e.name])throw new Error("a filter with this name already exists on this model");return this.state.options[e.name]=e,b(()=>this.state.options[e.name].enabled?t.current.filter(this.state.options[e.name].matches.bind(this)):t.current,50)}}function Ge(e={}){if(!e||typeof e!="object"||Object.keys(e).length===0)throw new Error("columns requires options to be an object with at least one property");return function(t){return this.state.options.columns=e,b(()=>t.current.map(n=>{let r={};for(let i of Object.keys(this.state.options.columns))this.state.options.columns[i]?.hidden||(r[i]=n[i]??null);return r}),50)}}function Je(e){return function(t){this.state.options.scroll=Object.assign({offset:0,rowHeight:26,rowCount:20,itemsPerRow:1,size:t.current.length},e);let n=this.state.options.scroll,r=n.scrollbar||n.container?.querySelector("[data-flow-scrollbar]");return r&&(n.container&&n.container.addEventListener("scroll",i=>{n.offset=Math.floor(n.container.scrollTop/(n.rowHeight*n.itemsPerRow))}),b(()=>{n.size=t.current.length*n.rowHeight,r.style.height=n.size+"px"},50)),b(()=>{n.container&&(n.rowCount=Math.ceil(n.container.getBoundingClientRect().height/n.rowHeight)),n.data=t.current;let i=Math.min(n.offset,t.current.length-1),s=i+n.rowCount;return s>t.current.length&&(s=t.current.length,i=s-n.rowCount),t.current.slice(i,s)},50)}}var ee=class extends HTMLElement{constructor(){super()}connectedCallback(){let t=this.getAttribute("rel"),n=document.getElementById(t);if(n){let r=n.content.cloneNode(!0);for(let i of r.childNodes){let s=i.cloneNode(!0);if(s.nodeType==document.ELEMENT_NODE&&(s.querySelectorAll("template").forEach(function(o){o.setAttribute("simply-render","")}),this.attributes))for(let o of this.attributes)o.name!="rel"&&s.setAttribute(o.name,o.value);this.parentNode.insertBefore(s,this)}this.parentNode.removeChild(this)}else(()=>{let i=new MutationObserver(()=>{n=document.getElementById(t),n&&(i.disconnect(),this.replaceWith(this))});i.observe(globalThis.document,{subtree:!0,childList:!0})})()}};customElements.get("simply-render")||customElements.define("simply-render",ee);globalThis.simply||(globalThis.simply={});Object.assign(globalThis.simply,{bind:Ee,flow:x,state:U,dom:J});var bt=globalThis.simply;})();
2
2
  //# sourceMappingURL=simply.flow.min.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/state.mjs", "../src/bind.transformers.mjs", "../src/dom.mjs", "../src/bind.render.mjs", "../src/bind.mjs", "../src/model.mjs", "../src/render.mjs", "../src/flow.mjs"],
4
- "sourcesContent": ["if (!Symbol.iterate) {\n Symbol.iterate = Symbol('iterate')\n}\nif (!Symbol.xRay) {\n Symbol.xRay = Symbol('xRay')\n}\nif (!Symbol.Signal) {\n Symbol.Signal = Symbol('Signal')\n}\n\nconst signalHandler = {\n get: (target, property, receiver) => {\n if (property===Symbol.xRay) {\n return target // don't notifyGet here, this is only called by set\n }\n if (property===Symbol.Signal) {\n return true\n }\n const value = target?.[property] // Reflect.get fails on a Set.\n notifyGet(receiver, property)\n if (typeof value === 'function') {\n if (Array.isArray(target)) {\n return (...args) => {\n let l = target.length\n // by binding the function to the receiver\n // all accesses in the function will be trapped\n // by the Proxy, so get/set/delete is all handled\n let result = value.apply(receiver, args)\n if (l != target.length) {\n notifySet(receiver, makeContext('length', { was: l, now: target.length }) )\n }\n return result\n }\n } else if (target instanceof Set || target instanceof Map) {\n return (...args) => {\n // node doesn't allow you to call set/map functions\n // bound to the receiver.. so using target instead\n // there are no properties to update anyway, except for size\n let s = target.size\n let result = value.apply(target, args)\n if (s != target.size) {\n notifySet(receiver, makeContext( 'size', { was: s, now: target.size }) )\n }\n // there is no efficient way to see if the function called\n // has actually changed the Set/Map, but by assuming the\n // 'setter' functions will change the results of the\n // 'getter' functions, effects should update correctly\n if (['set','add','clear','delete'].includes(property)) {\n notifySet(receiver, makeContext( { entries: {}, forEach: {}, has: {}, keys: {}, values: {}, [Symbol.iterator]: {} } ) )\n }\n return result\n }\n } else if (\n target instanceof HTMLElement\n || target instanceof Number\n || target instanceof String\n || target instanceof Boolean\n ) {\n return value.bind(target)\n } else {\n // support custom classes, hopefully\n return value.bind(receiver)\n }\n }\n if (value && typeof value == 'object') {\n return signal(value)\n }\n return value\n },\n set: (target, property, value, receiver) => {\n let current = target[property]\n if (current!==value) {\n target[property] = value\n notifySet(receiver, makeContext(property, { was: current, now: value } ) )\n }\n if (typeof current === 'undefined') {\n notifySet(receiver, makeContext(Symbol.iterate, {}))\n notifySet(receiver, makeContext('length', {}))\n }\n return true\n },\n has: (target, property) => { // receiver is not part of the has() call\n let receiver = signals.get(target) // so retrieve it here\n if (receiver) {\n notifyGet(receiver, property)\n }\n return Object.hasOwn(target, property)\n },\n deleteProperty: (target, property) => {\n if (typeof target[property] !== 'undefined') {\n let current = target[property]\n delete target[property]\n let receiver = signals.get(target) // receiver is not part of the trap arguments, so retrieve it here\n notifySet(receiver, makeContext(property,{ delete: true, was: current }))\n }\n return true\n },\n defineProperty: (target, property, descriptor) => {\n if (typeof target[property] === 'undefined') {\n let receiver = signals.get(target) // receiver is not part of the trap arguments, so retrieve it here\n notifySet(receiver, makeContext(Symbol.iterate, {}))\n }\n return Object.defineProperty(target, property, descriptor)\n },\n ownKeys: (target) => {\n let receiver = signals.get(target) // receiver is not part of the trap arguments, so retrieve it here\n notifyGet(receiver, Symbol.iterate)\n return Reflect.ownKeys(target)\n }\n\n}\n\n/**\n * Keeps track of the return signal for an update function, as well\n * as signals connected to other objects. \n * Makes sure that a given object or function always uses the same\n * signal\n */\nexport const signals = new WeakMap()\n\n/**\n * Creates a new signal proxy of the given object, that intercepts get/has and set/delete\n * to allow reactive functions to be triggered when signal values change.\n */\nexport function signal(v) {\n if (!v) {\n v = {}\n }\n if (v[Symbol.Signal]) { // there can be only one signal for any value\n return v\n }\n if (!signals.has(v)) {\n signals.set(v, new Proxy(v, signalHandler))\n }\n return signals.get(v)\n}\n\n\nlet tracers = []\nlet tracing = false\n/**\n * @param Signal|Function signal\n * If given a singal and property, this function lists all effects \n * that are currently listening to changes to that signal and property\n * returns a list with \n * - effect: the effect function (effect, throttledEffect, clockEffect)\n * - fn: the user provided function to this effect function\n * - signal: the connectedSignal to this user provided function\n * @param string prop \n * @return array of { effect, fn, signal }\n * \n * If given a function, it will enable any tracers added with addTracer\n * call the given function and then disable all tracers.\n * @return void\n */\nexport function trace(signal, prop) {\n if (typeof signal==='function') {\n tracing = true\n signal()\n tracing = false\n } else {\n const listeners = getListeners(signal, prop)\n return listeners.map(listener => {\n return {\n effect: listener.effectType,\n fn: listener.effectFunction,\n signal: signals.get(listener.effectFunction)\n }\n })\n }\n}\n\n/**\n * Adds a tracer. This is an object with a 'set' and/or 'get' function.\n * If enabled (with the trace() method) each access to notifyGet will \n * call the 'get' function. Each access to notifySet will call the 'set'\n * function.\n * @param tracer { get: fn, set: fn }\n * get: function(signal, property)\n * set: function(signal, context, listener)\n */\nexport function addTracer(tracer) {\n if (!tracer.get && !tracer.set) {\n throw new Error('simply.state: addTracer: missing \"get\" or \"set\" property in tracer', tracer)\n }\n if (tracer.get && typeof tracer.get!=='function') {\n throw new Error('simply.state: addTracer: \"get\" is not a function', tracer)\n }\n if (tracer.set && typeof tracer.set!=='function') {\n throw new Error('simply.state: addTracer: \"set\" is not a function', tracer)\n }\n tracers.push(tracer)\n}\n\nfunction callTracers(getset, ...params) {\n for (const tracer of tracers) {\n if (tracer[getset]) {\n tracer[getset](...params)\n }\n }\n}\n\nlet batchedListeners = new Set()\nlet batchMode = 0\n/**\n * Called when a signal changes a property (set/delete)\n * Triggers any reactor function that depends on this signal\n * to re-compute its values\n */\nexport function notifySet(self, context={}) {\n let listeners = []\n context.forEach((change, property) => {\n let propListeners = getListeners(self, property)\n if (propListeners?.length) {\n for (let listener of propListeners) {\n addContext(listener, makeContext(property,change))\n }\n listeners = listeners.concat(propListeners)\n }\n })\n listeners = new Set(listeners.filter(Boolean))\n if (listeners) {\n if (batchMode) {\n batchedListeners = batchedListeners.union(listeners)\n } else {\n const currentEffect = computeStack[computeStack.length-1]\n for (let listener of Array.from(listeners)) {\n if (listener!=currentEffect && listener?.needsUpdate) {\n if (tracing && tracers.length) {\n callTracers('set', self, context, listener)\n }\n listener()\n }\n clearContext(listener)\n }\n }\n }\n}\n\n\nexport function makeContext(property, change) {\n let context = new Map()\n if (typeof property === 'object') {\n for (let prop in property) {\n context.set(prop, property[prop])\n }\n } else {\n context.set(property, change)\n }\n return context\n}\n\nfunction addContext(listener, context) {\n if (!listener.context) {\n listener.context = context\n } else {\n context.forEach((change,property)=> {\n listener.context.set(property, change) // TODO: merge change if needed\n })\n }\n listener.needsUpdate = true\n}\n\nfunction clearContext(listener) {\n delete listener.context\n delete listener.needsUpdate\n}\n\n/**\n * Called when a signal property is accessed. If this happens\n * inside a reactor function--computeStack is not empty--\n * then it adds the current reactor (top of this stack) to its\n * listeners. These are later called if this property changes\n */\nexport function notifyGet(self, property) {\n let currentCompute = computeStack[computeStack.length-1]\n if (currentCompute) {\n if (tracing && tracers.length) {\n callTracers('get', self, property)\n }\n // get was part of a react() function, so add it\n setListeners(self, property, currentCompute)\n }\n}\n\n/**\n * Keeps track of which update() functions are dependent on which\n * signal objects and which properties. Maps signals to update fns\n */\nconst listenersMap = new WeakMap()\n\n/**\n * Keeps track of which signals and properties are linked to which\n * update functions. Maps update functions and properties to signals\n */\nconst computeMap = new WeakMap()\n\n/**\n * Returns the update functions for a given signal and property\n */\nfunction getListeners(self, property) {\n let listeners = listenersMap.get(self)\n return listeners ? Array.from(listeners.get(property) || []) : []\n}\n\n/**\n * Adds an update function (compute) to the list of listeners on\n * the given signal (self) and property\n */\nfunction setListeners(self, property, compute) {\n if (!listenersMap.has(self)) {\n listenersMap.set(self, new Map())\n }\n let listeners = listenersMap.get(self)\n if (!listeners.has(property)) {\n listeners.set(property, new Set())\n }\n listeners.get(property).add(compute)\n\n if (!computeMap.has(compute)) {\n computeMap.set(compute, new Map())\n }\n let connectedSignals = computeMap.get(compute)\n if (!connectedSignals.has(property)) {\n connectedSignals.set(property, new Set)\n }\n connectedSignals.get(property).add(self)\n}\n\n/**\n * Removes alle listeners that trigger the given reactor function (compute)\n * This happens when a reactor is called, so that it can set new listeners\n * based on the current call (code path)\n */\nfunction clearListeners(compute) {\n let connectedSignals = computeMap.get(compute)\n if (connectedSignals) {\n connectedSignals.forEach(property => {\n property.forEach(s => {\n let listeners = listenersMap.get(s)\n if (listeners.has(property)) {\n listeners.get(property).delete(compute)\n }\n })\n })\n }\n}\n\n/**\n * The top most entry is the currently running update function, used\n * to automatically record signals used in an update function.\n */\nlet computeStack = []\n\n/**\n * Used for cycle detection: effectStack contains all running effect\n * functions. If the same function appears twice in this stack, there\n * is a recursive update call, which would cause an infinite loop.\n */\nconst effectStack = []\n\nconst effectMap = new WeakMap()\n/**\n * Used for cycle detection: signalStack contains all used signals. \n * If the same signal appears more than once, there is a cyclical \n * dependency between signals, which would cause an infinite loop.\n */\nconst signalStack = []\n\n/**\n * Runs the given function at once, and then whenever a signal changes that\n * is used by the given function (or at least signals used in the previous run).\n */\nexport function effect(fn) {\n if (effectStack.findIndex(f => fn==f)!==-1) {\n throw new Error('Recursive update() call', {cause:fn})\n }\n effectStack.push(fn)\n\n let connectedSignal = signals.get(fn)\n if (!connectedSignal) {\n connectedSignal = signal({\n current: null\n })\n signals.set(fn, connectedSignal)\n }\n\n // this is the function that is called automatically\n // whenever a signal dependency changes\n const computeEffect = function computeEffect() {\n if (signalStack.findIndex(s => s==connectedSignal)!==-1) {\n throw new Error('Cyclical dependency in update() call', { cause: fn})\n }\n // remove all dependencies (signals) from previous runs \n clearListeners(computeEffect)\n computeEffect.effectFunction = fn\n computeEffect.effectType = effect\n // record new dependencies on this run\n computeStack.push(computeEffect)\n // prevent recursion\n signalStack.push(connectedSignal)\n // call the actual update function\n let result\n try {\n result = fn(computeEffect, computeStack, signalStack)\n } finally {\n // stop recording dependencies\n computeStack.pop()\n // stop the recursion prevention\n signalStack.pop()\n if (result instanceof Promise) {\n result.then((result) => {\n connectedSignal.current = result\n })\n } else {\n connectedSignal.current = result\n }\n }\n }\n computeEffect.fn = fn\n effectMap.set(connectedSignal, computeEffect)\n\n // run the computEffect immediately upon creation\n computeEffect()\n return connectedSignal\n}\n\n\nexport function destroy(connectedSignal) {\n // find the computeEffect associated with this signal\n const computeEffect = effectMap.get(connectedSignal)?.deref()\n if (!computeEffect) {\n return\n }\n\n // remove all listeners for this effect\n clearListeners(computeEffect)\n\n // remove all references to connectedSignal\n let fn = computeEffect.fn\n signals.remove(fn)\n\n effectMap.delete(connectedSignal)\n\n // if no other references to connectedSignal exist, it will be garbage collected\n}\n\n/**\n * Inside a batch() call, any changes to signals do not trigger effects\n * immediately. Instead, immediately after finishing the batch() call,\n * these effects will be called. Effects that are triggered by multiple\n * signals are called only once.\n * @param Function fn batch() calls this function immediately\n * @result mixed the result of the fn() function call\n */\nexport function batch(fn) {\n batchMode++\n let result\n try {\n result = fn()\n } finally {\n if (result instanceof Promise) {\n result.then(() => {\n batchMode--\n if (!batchMode) {\n runBatchedListeners()\n }\n })\n } else {\n batchMode--\n if (!batchMode) {\n runBatchedListeners()\n }\n }\n }\n return result\n}\n\nfunction runBatchedListeners() {\n let copyBatchedListeners = Array.from(batchedListeners)\n batchedListeners = new Set()\n const currentEffect = computeStack[computeStack.length-1]\n for (let listener of copyBatchedListeners) {\n if (listener!=currentEffect && listener?.needsUpdate) {\n listener()\n }\n clearContext(listener)\n }\n}\n\n/**\n * A throttledEffect is run immediately once. And then only once\n * per throttleTime (in ms).\n * @param Function fn the effect function to run whenever a signal changes\n * @param int throttleTime in ms\n * @returns signal with the result of the effect function fn\n */\nexport function throttledEffect(fn, throttleTime) {\n if (effectStack.findIndex(f => fn==f)!==-1) {\n throw new Error('Recursive update() call', {cause:fn})\n }\n effectStack.push(fn)\n\n let connectedSignal = signals.get(fn)\n if (!connectedSignal) {\n connectedSignal = signal({\n current: null\n })\n signals.set(fn, connectedSignal)\n }\n\n let throttled = false\n let hasChange = true\n // this is the function that is called automatically\n // whenever a signal dependency changes\n const computeEffect = function computeEffect() {\n if (signalStack.findIndex(s => s==connectedSignal)!==-1) {\n throw new Error('Cyclical dependency in update() call', { cause: fn})\n }\n if (throttled && throttled>Date.now()) {\n hasChange = true\n return\n }\n // remove all dependencies (signals) from previous runs \n clearListeners(computeEffect)\n // record new dependencies on this run\n computeEffect.effectFunction = fn\n computeEffect.effectType = throttledEffect\n computeStack.push(computeEffect)\n // prevent recursion\n signalStack.push(connectedSignal)\n // call the actual update function\n let result\n try {\n result = fn(computeEffect, computeStack, signalStack)\n } finally {\n hasChange = false\n // stop recording dependencies\n computeStack.pop()\n // stop the recursion prevention\n signalStack.pop()\n if (result instanceof Promise) {\n result.then((result) => {\n connectedSignal.current = result\n })\n } else {\n connectedSignal.current = result\n }\n }\n throttled = Date.now()+throttleTime\n globalThis.setTimeout(() => {\n if (hasChange) {\n computeEffect()\n }\n }, throttleTime)\n }\n // run the computEffect immediately upon creation\n computeEffect()\n return connectedSignal\n}\n\n// refactor: Class clock() with an effect() method\n// keep track of effects per clock, and add clock property to the effect function\n// on notifySet add clock.effects to clock.needsUpdate list\n// on clock.tick() (or clock.time++) run only the clock.needsUpdate effects \n// (first create a copy and reset clock.needsUpdate, then run effects)\nexport function clockEffect(fn, clock) {\n let connectedSignal = signals.get(fn)\n if (!connectedSignal) {\n connectedSignal = signal({\n current: null\n })\n signals.set(fn, connectedSignal)\n }\n\n let lastTick = -1 // clock.time should start at 0 or larger\n let hasChanged = true // make sure the first run goes through\n // this is the function that is called automatically\n // whenever a signal dependency changes\n const computeEffect = function computeEffect() {\n if (lastTick < clock.time) {\n if (hasChanged) {\n // remove all dependencies (signals) from previous runs \n clearListeners(computeEffect)\n computeEffect.effectFunction = fn\n computeEffect.effectType = clockEffect\n // record new dependencies on this run\n computeStack.push(computeEffect)\n // make sure the clock.time signal is a dependency\n lastTick = clock.time\n // call the actual update function\n let result \n try {\n result = fn(computeEffect, computeStack)\n } finally {\n // stop recording dependencies\n computeStack.pop()\n if (result instanceof Promise) {\n result.then((result) => {\n connectedSignal.current = result\n })\n } else {\n connectedSignal.current = result\n }\n hasChanged = false\n }\n } else {\n lastTick = clock.time\n }\n } else {\n hasChanged = true\n }\n }\n // run the computEffect immediately upon creation\n computeEffect()\n return connectedSignal\n}\n\n/**\n * Any signal access inside `fn` is not tracked for the current effect.\n * Any changes to signals inside `fn` will still trigger any effect listening to thoses signals.\n * @param fn Function that is called immediately. Its result is returned.\n * @result mixed\n */\nexport function untracked(fn) {\n const pos = computeStack.length-1\n const remember = computeStack[pos]\n computeStack[pos] = false\n try {\n return fn()\n } finally {\n computeStack[pos] = remember\n }\n}\n\n/**\n * This function will created a copy of the input, recursive if deep==true\n * It will replace any non-clonable values with null\n * It will replace signals with a clone of their target\n * It will keep cyclical references intact\n * @param value Object\n * @param deep Boolean default: false\n * @return mixed a clone of the value\n */\nexport function clone(value, deep=false)\n{\n let seen = new Map()\n const innerClone = function(value) {\n if (seen.has(value)) {\n return seen.get(value)\n }\n switch(typeof value) {\n case 'object':\n if (!value) {\n return value\n }\n if (Array.isArray(value)) {\n let result = []\n if (!deep) {\n result = value.slice()\n seen.set(value, result)\n return result\n }\n seen.set(value, result)\n for (const key of value) {\n result[key] = innerClone(value[key])\n }\n } else if (!value.constructor || value.constructor===Object) {\n let result = {}\n if (!value.constructor) {\n result = Object.create(null)\n }\n seen.set(value, result)\n for (const key in value) {\n result[key] = deep ? innerClone(value[key]) : value[key]\n }\n return result\n } else {\n // cannot clone, ignore? throw error?\n return value\n }\n break\n default:\n return null // ignore non-cloneable values\n break\n }\n }\n return innerClone(value)\n}", "export function escape_html(context, next) {\n let content = context.value?.innerHTML\n if (typeof context.value == 'string') {\n content = context.value\n context.value = { innerHTML: content }\n }\n if (content) {\n content = content.replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n context.value.innerHTML = content\n }\n next(context)\n}\n\nexport function fixed_content(context, next) {\n if (typeof context.value == 'string') {\n context.value = {}\n } else {\n delete context.value?.innerHTML\n }\n next(context)\n}\n", "import { signals, signal as stateSignal, notifyGet, notifySet, makeContext } from './state.mjs'\n\nconst domSignalHandler = {\n get: (target, property, receiver) => {\n if (property===Symbol.xRay) {\n return target // don't notifyGet here, this is only called by set\n }\n if (property===Symbol.Signal) {\n return true\n }\n const value = target?.[property]\n notifyGet(receiver, property)\n if (typeof value === 'function') {\n return value.bind(target) // make sure element functions are not linked to the proxy\n }\n if (value && typeof value == 'object') {\n return stateSignal(value)\n }\n return value\n },\n has: (target, property) => {\n let receiver = signals.get(target)\n if (receiver) {\n notifyGet(receiver, property)\n }\n return Object.hasOwn(target, property)\n },\n ownKeys: (target) => {\n let receiver = signals.get(target) // receiver is not part of the trap arguments, so retrieve it here\n if (receiver) {\n notifyGet(receiver, iterate)\n }\n return Reflect.ownKeys(target)\n }\n}\n\nexport function signal(el, options) {\n if (el[Symbol.xRay]) {\n return el\n }\n if (!signals.has(el)) {\n signals.set(el, new Proxy(el, domSignalHandler))\n domListen(el, signals.get(el), options)\n }\n return signals.get(el)\n}\n\nconst observers = new WeakMap()\n\nfunction domListen(el, signal, options) {\n const defaultOptions = {\n characterData: true,\n subtree: true,\n attributes: true,\n attributesOldValue: true\n }\n if (!options) {\n options = defaultOptions\n }\n let oldContentHTML = el.innerHTML\n let oldContentText = el.innerText\n if (!observers.has(el)) {\n const observer = new MutationObserver((mutationList, observer) => {\n // collect changes\n const changes = {}\n for (const mutation of mutationList) {\n if (mutation.type==='attributes') {\n // check if any listeners for each attribute\n changes[mutation.attributeName] = mutation.attributeOldValue\n } else if (mutation.type==='subtree' || mutation.type==='characterData') {\n // change on innerHTML/innerText\n if (el.innerHTML != oldContentHTML) {\n changes.innerHTML = oldContentHTML\n oldContentHTML = el.innerHTML\n }\n if (el.innerText != oldContentText) {\n changes.innerText = oldContentText\n oldContentText = el.innerText\n }\n } else if (mutation.type==='childList') {\n changes.children = { //FIXME: overwrites changes in this list path if list is rendered multiple times\n was: Array.from(el.children) //FIXME; fill in 'now'\n }\n changes.length = -1 //FIXME: don't do this :)\n } else {\n console.log('nothing to do for',el,mutation.type)\n }\n }\n for (const prop in changes) {\n notifySet(signal, makeContext(prop, { was: changes[prop], now: el[prop] }))\n }\n })\n observer.observe(el, options)\n observers.set(el, observer)\n //@TODO: unregister the observer when el is removed from the dom (after a timeout)\n if (el.matches('input, textarea, select')) {\n let prevValue = el.value\n el.addEventListener('change', (evt) => {\n notifySet(signal, makeContext('value', { was: prevValue, now: el.value }))\n prevValue = el.value\n })\n if (el.matches('input, textarea')) {\n el.addEventListener('input', (evt) => {\n notifySet(signal, makeContext('value', { was: prevValue, now: el.value }))\n prevValue = el.value\n })\n }\n }\n }\n}\n", "/*\n * Default renderers for data binding\n * Will be used unless overriden in the SimplyBind options parameter\n */\nimport { signal as domSignal } from './dom.mjs'\nimport { throttledEffect, effect, untracked, batch } from './state.mjs'\nimport { getValueByPath } from './bind.mjs'\n/**\n * This function is used by default to render dom elements with the `data-flow-field` attribute.\n * It will switch to only switching in template content if the context has any templates.\n * Otherwise it will call the matching render function depending on the tagName of the\n * context.element\n */\nexport function field(context)\n{\n if (context.templates?.length) {\n fieldByTemplates.call(this, context)\n // TODO: check if existence of one or more templates must mean that\n // only the template rendering is applied, instead of also rendering attributes\n } else if (Object.hasOwnProperty.call(this.options.renderers, context.element.tagName)) {\n const renderer = this.options.renderers[context.element.tagName]\n if (renderer) {\n renderer.call(this, context)\n }\n } else if (this.options.renderers['*']) {\n this.options.renderers['*'].call(this, context)\n }\n return context\n}\n\n/**\n * This function is used by default to render DOM elements with the `data-flow-list` attribute.\n * The context.value must be an array. And context.templates must not be empty.\n */\nexport function list(context)\n{\n if (!Array.isArray(context.value)) {\n context.value = [context.value]\n }\n // make sure this effect is triggered if the length of the array changes\n const length = context.value.length\n if (!context.templates?.length) {\n console.error('No templates found in', context.element)\n } else {\n arrayByTemplates.call(this, context)\n }\n return context\n}\n\n/**\n * This function is used by default to render DOM elements with the `data-flow-map` attribute.\n * The context.value must be a non-null object. And context.templates must not be empty.\n */\nexport function map(context)\n{\n if (typeof context.value != 'object' || !context.value) {\n console.error('Value is not an object.', context.element, context.path, context.value)\n } else if (!context.templates?.length) {\n console.error('No templates found in', context.element)\n } else {\n objectByTemplates.call(this, context)\n }\n return context\n}\n\nfunction isInt(s) {\n if (parseInt(s)==s) {\n return true\n }\n}\n\n/**\n * This function sets a given value on the given path, starting at the given root.\n * It will automatically create objects if a path part does not yet exist.\n * @param root the root object\n * @param path a JSON path\n * @param value the value to set\n */\nexport function setValueByPath(root, path, value)\n{\n batch(() => {\n let parts = path.split('.')\n let curr = root\n let part\n part = parts.shift()\n let prev = null\n let prevPart = null\n let prevCurr = curr\n while (part && curr) {\n prevCurr = curr\n part = decodeURIComponent(part)\n if (part=='0' && !Array.isArray(curr)) {\n // ignore so that data-flow-list=\"nonarray\" will work\n } else if (part==':key') {\n // FIXME: should change the key, not the value... not supported yet?\n throw new Error('setting key not yet supported')\n curr = prevPart\n } else if (part==':value') {\n // do nothing\n } else if (Array.isArray(curr) && !isInt(part) && typeof curr[part]=='undefined') {\n prev = curr[0]\n curr = curr[0][part] // so that data-flow-field=\"array.foo\" works\n } else {\n prev = curr\n curr = curr[part]\n }\n prevPart = part\n part = parts.shift()\n if (part && !curr) {\n // path in html does not exist yet, so create it\n const intKey = parseInt(part)\n if (intKey>=0 && part===''+intKey) {\n prevCurr[prevPart] = []\n } else {\n prevCurr[prevPart] = {}\n }\n curr = prevCurr[prevPart]\n }\n }\n if (prev && prevPart && prev[prevPart]!==value) {\n if (value && typeof value=='object') {\n curr = prev[prevPart]\n if (!curr) {\n // last part of path in html does not exist yet, create it\n prev[prevPart] = {}\n curr = prev[prevPart]\n }\n for (const prop in value) {\n if (curr[prop]!==value[prop]) {\n curr[prop] = value[prop]\n }\n }\n } else {\n prev[prevPart] = value\n }\n }\n })\n}\n\n/**\n * Renders an array value by applying templates for each entry\n * Replaces or removes existing DOM children if needed\n * Reuses (doesn't touch) DOM children if template doesn't change\n * FIXME: this doesn't handle situations where there is no matching template\n * this messes up self healing. check renderObjectByTemplates for a better implementation\n */\nexport function arrayByTemplates(context)\n{\n const attribute = this.options.attribute\n\n let items = context.element.querySelectorAll(':scope > ['+attribute+'-key]')\n // do single merge strategy for now, in future calculate optimal merge strategy from a number\n // now just do a delete if a key <= last key, insert if a key >= last key\n let lastKey = 0\n let skipped = 0\n context.list = context.value\n for (let item of items) {\n let currentKey = parseInt(item.getAttribute(attribute+'-key'))\n if (currentKey>lastKey) {\n // insert before\n context.index = lastKey\n context.element.insertBefore(this.applyTemplate(context), item)\n } else if (currentKey<lastKey) {\n // remove this\n item.remove()\n } else {\n // check that all data-bind params start with current json path or ':root', otherwise replaceChild\n let bindings = Array.from(item.querySelectorAll(`[${attribute}]`))\n if (item.matches(`[${attribute}]`)) {\n bindings.unshift(item)\n }\n let needsReplacement = bindings.find(b => {\n let databind = b.getAttribute(attribute)\n return (databind.substr(0,5)!==':root' \n && databind.substr(0, context.path.length)!==context.path)\n })\n if (!needsReplacement) {\n if (item[Symbol.bindTemplate]) {\n let newTemplate = this.findTemplate(context.templates, context.list[lastKey])\n if (newTemplate != item[Symbol.bindTemplate]){\n needsReplacement = true\n if (!newTemplate) {\n skipped++\n }\n }\n }\n }\n if (needsReplacement) {\n context.index = lastKey\n context.element.replaceChild(this.applyTemplate(context), item)\n }\n }\n lastKey++\n if (lastKey>=context.value.length) {\n break\n }\n }\n items = context.element.querySelectorAll(':scope > ['+attribute+'-key]')\n let length = items.length + skipped\n if (length > context.value.length) {\n while (length > context.value.length) {\n let child = context.element.querySelectorAll(':scope > :not(template)')?.[length-1]\n child?.remove()\n length--\n }\n } else if (length < context.value.length ) {\n while (length < context.value.length) {\n context.index = length\n context.element.appendChild(this.applyTemplate(context))\n length++\n }\n }\n if (this.options.twoway) {\n const s = domSignal(context.element, {\n childList: true\n })\n throttledEffect(() => {\n const children = Array.from(s.children)\n batch(() => {\n untracked(() => {\n let key=0\n const currentList = context.value.slice()\n for (const item of children) {\n if (item.tagName==='TEMPLATE') {\n continue\n }\n if (item.dataset.flowKey) {\n if (item.dataset.flowKey!=key) {\n setValueByPath(this.options.root, context.path+'.'+key,\n currentList[item.dataset.flowKey])\n }\n key++\n }\n }\n if (context.value.length>key) {\n // remove extra values\n const source = getValueByPath(this.options.root, context.path)\n source.length = key\n }\n })\n })\n })\n }\n}\n\n/**\n * Renders an object value by applying templates for each entry (Object.entries)\n * Replaces,moves or removes existing DOM children if needed\n * Reuses (doesn't touch) DOM children if template doesn't change\n */\nexport function objectByTemplates(context)\n{\n const attribute = this.options.attribute\n context.list = context.value\n\n let items = Array.from(context.element.querySelectorAll(':scope > ['+attribute+'-key]'))\n for (let key in context.list) {\n context.index = key\n let item = items.shift()\n if (!item) { // more properties than rendered items\n let clone = this.applyTemplate(context)\n context.element.appendChild(clone)\n continue\n }\n if (item.getAttribute(attribute+'-key')!=key) { \n // next item doesn't match key\n items.unshift(item) // put item back for next cycle\n let outOfOrderItem = context.element.querySelector(':scope > ['+attribute+'-key=\"'+key+'\"]') //FIXME: escape key\n if (!outOfOrderItem) {\n let clone = this.applyTemplate(context)\n context.element.insertBefore(clone, item)\n continue // new template doesn't need replacement, so continue \n } else {\n context.element.insertBefore(outOfOrderItem, item)\n item = outOfOrderItem // check needsreplacement next\n items = items.filter(i => i!=outOfOrderItem)\n }\n }\n let newTemplate = this.findTemplate(context.templates, context.list[context.index])\n if (newTemplate != item[Symbol.bindTemplate]){\n let clone = this.applyTemplate(context)\n context.element.replaceChild(clone, item)\n }\n }\n // clean up remaining items\n while (items.length) {\n let item = items.shift()\n item.remove()\n }\n}\n\n/**\n * renders the contents of an html element by rendering\n * a matching template, once.\n */\nexport function fieldByTemplates(context)\n{\n const rendered = context.element.querySelector(':scope > :not(template)')\n const template = this.findTemplate(context.templates, context.value)\n context.parent = getParentPath(context.element)\n if (rendered) {\n if (template) {\n if (rendered?.[Symbol.bindTemplate] != template) {\n const clone = this.applyTemplate(context)\n context.element.replaceChild(clone, rendered)\n }\n } else {\n context.element.removeChild(rendered)\n }\n } else if (template) {\n const clone = this.applyTemplate(context)\n context.element.appendChild(clone)\n }\n}\n\nfunction getParentPath(el, attribute)\n{\n const parentEl = el.parentElement?.closest(`[${attribute}-list],[${attribute}-map]`)\n if (!parentEl) {\n return ''\n }\n if (parentEl.hasAttribute(`${attribute}-list`)) {\n return parentEl.getAttribute(`${attribute}-list`)+'.'\n }\n return parentEl.getAttribute(`${attribute}-map`)+'.'\n}\n\n/**\n * renders a single input type\n * for radio/checkbox inputs it only sets the checked attribute to true/false\n * if the value attribute matches the current value\n * for other inputs the value attribute is updated\n */\nexport function input(context)\n{\n const el = context.element\n let value = context.value\n\n element.call(this, context)\n if (typeof value == 'undefined') {\n value = ''\n }\n if (el.type=='checkbox' || el.type=='radio') {\n if (matchValue(el.value, value)) {\n el.checked = true\n } else {\n el.checked = false\n }\n } else if (!matchValue(el.value, value)) {\n el.value = ''+value\n }\n}\n\n/**\n * Sets the value of the button, doesn't touch the innerHTML\n */\nexport function button(context)\n{\n element.call(this, context, 'value')\n}\n\n/**\n * Sets the selected attribute of select options\n */\nexport function select(context)\n{\n const el = context.element\n let value = context.value\n\n if (value === null) {\n value = ''\n }\n if (typeof value!='object') {\n if (el.multiple) {\n if (Array.isArray(value)) { //FIXME: cannot be true, since typeof != 'object'\n for (let option of el.options) {\n if (value.indexOf(option.value)===false) {\n option.selected = false\n } else {\n option.selected = true\n }\n }\n }\n } else {\n let option = el.options.find(o => matchValue(o.value,value))\n if (option) {\n option.selected = true\n option.setAttribute('selected', true)\n }\n }\n } else { // value is a non-null object\n if (value.options) {\n setSelectOptions(el, value.options)\n }\n if (value.selected) {\n select(Object.asssign({}, context, {value:value.selected}))\n }\n setProperties(el, value, 'name', 'id', 'selectedIndex', 'className') // allow innerHTML? if so call element instead\n }\n}\n\n/**\n * adds a single option to a select element. The option.text property is optional, if not set option.value is used.\n * @param select The select element\n * @param option An option descriptor, either a string, object with {text,value,defaultSelected,selected} properties or an Option object\n */\nexport function addOption(select, option)\n{\n if (!option) {\n return\n }\n if (typeof option !== 'object') {\n select.options.add(new Option(''+option))\n } else if (option.text) {\n select.options.add(new Option(option.text, option.value, option.defaultSelected, option.selected))\n } else if (typeof option.value != 'undefined') {\n select.options.add(new Option(''+option.value, option.value, option.defaultSelected, option.selected))\n }\n}\n\n/**\n * This function clears all existing options of a select element, and adds the specified options.\n */\nexport function setSelectOptions(select,options)\n{\n //@TODO: only update in case of changes?\n select.innerHTML = ''\n if (Array.isArray(options)) {\n for (const option of options) {\n addOption(select, option)\n }\n } else if (options && typeof options == 'object') {\n for (const option in options) {\n addOption(select, { text: options[option], value: option })\n }\n }\n}\n\n/**\n * Sets the innerHTML and href, id, title, target, name, newwindow, nofollow attributes of an anchor\n */\nexport function anchor(context)\n{\n element.call(this, context, 'target', 'href', 'name', 'newwindow', 'nofollow')\n if (this.options.twoway) {\n batch(() => {\n updateProperties.call(this, context, ['target', 'href', 'name', 'newwindow', 'nofollow'])\n })\n }\n}\n\n/**\n * Sets the title, id, alt and src attributes of an image.\n */\nexport function image(context)\n{\n setProperties(context.element, context.value, 'title', 'alt', 'src', 'id')\n if (this.options.twoway) {\n batch(() => {\n updateProperties.call(this, context, ['title', 'alt', 'src', 'id'])\n })\n }\n}\n\n/**\n * Sets the title, id and src attribute of an iframe\n */\nexport function iframe(context)\n{\n setProperties(context.element, context.value, 'title', 'src', 'id')\n if (this.options.twoway) {\n batch(() => {\n updateProperties.call(this, context, ['title','src','id'])\n })\n }\n}\n\n/**\n * Sets the content and id attribute of a meta element\n */\nexport function meta(context)\n{\n setProperties(context.element, context.value, 'content', 'id')\n if (this.options.twoway) {\n batch(() => {\n updateProperties.call(this, context, ['content','id'])\n })\n }\n}\n\nconst domSignals = new WeakMap()\n\n/**\n * sets the innerHTML and title and id properties of any HTML element\n */\nexport function element(context, ...extraprops)\n{\n const el = context.element\n let value = context.value\n let valueIsString = false\n if (typeof value!='undefined' && value!==null) {\n let strValue = ''+value\n if (typeof value!='object' || strValue.substring(0,8)!='[object ') {\n value = { innerHTML: value }\n valueIsString = true\n }\n }\n const props = ['innerHTML','title','id','className'].concat(extraprops)\n setProperties(el, value, ...props)\n if (this.options.twoway) {\n batch(() => {\n updateProperties.call(this, context, props, valueIsString)\n })\n }\n}\n\nexport function updateProperties(context, props, valueIsString) {\n if (domSignals.has(context.element)) {\n return\n }\n const s = domSignal(context.element)\n domSignals.set(context.element, s)\n //TODO: run reverse transformers (extract)\n throttledEffect(() => {\n let updateValue = s.innerHTML //incorrect: in an anchor this could be s.href\n if (!valueIsString) {\n updateValue = getProperties(s, ...props)\n }\n untracked(() => {\n // don't trigger this effect when the data changes (root.path)\n setValueByPath(this.options.root, context.path, updateValue)\n })\n })\n}\n\n/**\n * Sets a list of properties on a dom element, equal to \n * the string value of a data object\n * only updates the dom element if the property doesn't match\n */\nexport function setProperties(el, data, ...properties) {\n if (!data || typeof data!=='object') {\n return\n }\n for (const property of properties) {\n if (typeof data[property] === 'undefined') {\n continue\n }\n if (matchValue(el[property], data[property])) {\n continue\n }\n if (data[property] === null) {\n el[property] = ''\n } else {\n el[property] = ''+data[property]\n }\n }\n}\n\nexport function getProperties(el, ...properties) {\n const result = {}\n for (const property of properties) {\n switch(property) {\n default: \n result[property] = el[property]\n break\n }\n }\n return result\n}\n\n/**\n * Returns true if a matches b, either by having the\n * same string value, or matching string :empty against a falsy value\n */\nexport function matchValue(a,b)\n{\n if (a==':empty' && !b) {\n return true\n }\n if (b==':empty' && !a) {\n return true\n }\n if (''+a == ''+b) {\n return true\n }\n return false\n}\n", "import { throttledEffect, destroy } from './state.mjs'\nimport { escape_html, fixed_content } from './bind.transformers.mjs'\nimport * as render from './bind.render.mjs'\n\nif (!Symbol.bindTemplate) {\n Symbol.bindTemplate = Symbol('bindTemplate')\n}\n\n/**\n * Implements one way databinding, updating dom elements with matching attributes\n * to changes in signals (see state.mjs)\n * \n * @class\n */\nclass SimplyBind\n{\n \n /**\n * @param Object options - a set of options for this instance, options may include:\n * - root (signal) (required) - the root data object that contains al signals that can be bound\n * - container (HTMLElement) - the dom element to use as the root for all bindings\n * - attribute (string) - the prefix for the field, list and map attributes, e.g. 'data-bind'\n * - transformers (object name:function) - a map of transformer names and functions\n * - render (object with field, list and map properties)\n */\n constructor(options)\n {\n /**\n * A map of HTMLElements and the data bindings on each, in the form of \n * the connectedSignal returned by the (throttled)Effect.\n * @type {Map}\n * @public\n */\n this.bindings = new Map()\n\n const defaultTransformers = {\n escape_html,\n fixed_content\n }\n const defaultOptions = {\n container: document.body,\n attribute: 'data-flow',\n transformers: defaultTransformers,\n render: {\n field: [render.field],\n list: [render.list],\n map: [render.map]\n },\n renderers: {\n 'INPUT':render.input,\n 'BUTTON':render.button,\n 'SELECT':render.select,\n 'A':render.anchor,\n 'IMG':render.image,\n 'IFRAME':render.iframe,\n 'META':render.meta,\n 'TEMPLATE':null,\n '*':render.element\n },\n twoway: false\n }\n if (!options?.root) {\n throw new Error('bind needs at least options.root set')\n }\n this.options = Object.assign({}, defaultOptions, options)\n if (options.transformers) {\n this.options.transformers = Object.assign({}, defaultTransformers, options?.transformers)\n }\n const attribute = this.options.attribute\n const bindAttributes = [attribute+'-field',attribute+'-list',attribute+'-map']\n const transformAttribute = attribute+'-transform'\n\n const getBindingAttribute = (el) => {\n const foundAttribute = bindAttributes.find(attr => el.hasAttribute(attr))\n if (!foundAttribute) {\n console.error('No matching attribute found',el,bindAttributes)\n }\n return foundAttribute\n }\n\n // sets up the effect that updates the element if its\n // data binding value changes\n const renderElement = (el) => {\n this.bindings.set(el, throttledEffect(() => {\n if (!el.isConnected) {\n // el is no longer part of this document\n untrack(el, this.getBindingPath(el))\n destroy(this.bindings.get(el))\n // doing this here instead of in a mutationobserver\n // allows an element to be temporary removed and then inserted\n // without the binding having to be reset\n return\n }\n let context = {\n templates: el.querySelectorAll(':scope > template'),\n attribute: getBindingAttribute(el)\n }\n context.path = this.getBindingPath(el)\n context.value = getValueByPath(this.options.root, context.path)\n context.element = el\n track(el, context)\n runTransformers(context)\n }, 50))\n }\n\n // finds and runs applicable transformers\n // creates a stack of transformers, calls the topmost\n // each transformer can opt to call the next or not\n // transformers should return the context object (possibly altered)\n const runTransformers = (context) => {\n let transformers\n switch(context.attribute) {\n case this.options.attribute+'-field':\n transformers = Array.from(this.options.render.field)\n break\n case this.options.attribute+'-list':\n transformers = Array.from(this.options.render.list)\n break\n case this.options.attribute+'-map':\n transformers = Array.from(this.options.render.map)\n break\n default:\n throw new Error('no valid context attribute specified',context)\n break\n }\n if (context.element.hasAttribute(transformAttribute)) {\n context.element.getAttribute(transformAttribute)\n .split(' ').filter(Boolean)\n .forEach(t => {\n if (this.options.transformers[t]) {\n transformers.push(this.options.transformers[t])\n } else {\n console.warn('No transformer with name '+t+' configured', {cause:context.element})\n }\n })\n }\n let next\n for (let transformer of transformers) {\n next = ((next, transformer) => {\n return (context) => {\n return transformer.call(this, context, next)\n }\n })(next, transformer)\n }\n next(context)\n }\n\n // given a set of elements with data bind attribute\n // this renders each of those elements\n const applyBindings = (bindings) => {\n for (let bindingEl of bindings) {\n if (!this.bindings.get(bindingEl)) { // bindingEl may have moved from somewhere else in this document\n renderElement(bindingEl)\n }\n }\n }\n\n // this handles the mutation observer changes\n // if any element is added, and has a data bind attribute\n // it applies that data binding\n const updateBindings = (changes) => {\n const selector = `[${attribute}-field],[${attribute}-list],[${attribute}-map]`\n for (const change of changes) {\n if (change.type==\"childList\" && change.addedNodes) {\n for (let node of change.addedNodes) {\n if (node instanceof HTMLElement) {\n let bindings = Array.from(node.querySelectorAll(selector))\n if (node.matches(selector)) {\n bindings.unshift(node)\n }\n if (bindings.length) {\n applyBindings(bindings)\n }\n }\n }\n }\n }\n }\n\n // this responds to elements getting added to the dom\n // and if any have data bind attributes, it applies those bindings\n this.observer = new MutationObserver((changes) => {\n updateBindings(changes)\n })\n\n this.observer.observe(this.options.container, {\n subtree: true,\n childList: true\n })\n\n // this finds elements with data binding attributes and applies those bindings\n // must come after setting up the observer, or included templates\n // won't trigger their own bindings\n const bindings = this.options.container.querySelectorAll(\n ':is(['+this.options.attribute+'-field]'+\n ',['+this.options.attribute+'-list]'+\n ',['+this.options.attribute+'-map]):not(template)'\n )\n if (bindings.length) {\n applyBindings(bindings)\n }\n\n }\n\n /**\n * Finds the first matching template and creates a new DocumentFragment\n * with the correct data bind attributes in it (prepends the current path)\n * @param Context context\n * @return DocumentFragment\n */\n applyTemplate(context)\n {\n const path = context.path\n const parent = context.parent\n const templates = context.templates\n const list = context.list\n const index = context.index\n const value = list ? list[index] : context.value\n\n let template = this.findTemplate(templates, value)\n if (!template) {\n let result = new DocumentFragment()\n result.innerHTML = '<!-- no matching template -->'\n return result\n }\n let clone = template.content.cloneNode(true)\n if (!clone.children?.length) {\n return clone\n }\n if (clone.children.length>1) {\n throw new Error('template must contain a single root node', { cause: template })\n }\n const attribute = this.options.attribute\n\n const attributes = [attribute+'-field',attribute+'-list',attribute+'-map']\n const bindings = clone.querySelectorAll(`[${attribute}-field],[${attribute}-list],[${attribute}-map]`)\n for (let binding of bindings) {\n if (binding.tagName=='TEMPLATE') {\n continue\n }\n const attr = attributes.find(attr => binding.hasAttribute(attr))\n let bind = binding.getAttribute(attr)\n bind = this.applyLinks(template.links, bind)\n if (bind.substring(0, ':root.'.length)==':root.') {\n binding.setAttribute(attr, bind.substring(':root.'.length))\n } else if (bind==':value' && index!=null) {\n binding.setAttribute(attr, path+'.'+index)\n } else if (index!=null) {\n binding.setAttribute(attr, path+'.'+index+'.'+bind)\n } else {\n binding.setAttribute(attr, parent+bind)\n }\n }\n if (typeof index !== 'undefined') {\n clone.children[0].setAttribute(attribute+'-key',index)\n }\n // keep track of the used template, so if that changes, the item can be updated\n clone.children[0][Symbol.bindTemplate] = template\n\n // return clone, not the firstChild, so that all whitespace is cloned as well\n return clone\n }\n\n parseLinks(links)\n {\n let result = {}\n links = links.split(';').map(link => link.trim())\n for (let link of links) {\n link = link.split('=')\n result[link[0].trim()] = link[1].trim()\n }\n return result\n }\n\n applyLinks(links, value)\n {\n for (let link in links) {\n if (value.startsWith(link+'.')) {\n return links[link] + value.substr(link.length)\n } else if (value==link) {\n return links[link]\n }\n }\n return value\n }\n\n /**\n * Returns the path referenced in either the field, list or map attribute\n * @param HTMLElement el\n * @return string The path referenced, or void\n */\n getBindingPath(el)\n {\n const attributes = [\n this.options.attribute+'-field', \n this.options.attribute+'-list',\n this.options.attribute+'-map'\n ]\n for (let attr of attributes) {\n if (el.hasAttribute(attr)) {\n return el.getAttribute(attr)\n }\n }\n }\n\n /**\n * Finds the first template from an array of templates that\n * matches the given value. \n */\n findTemplate(templates, value)\n {\n const templateMatches = t => {\n // find the value to match against (e.g. data-bind=\"foo\")\n let path = this.getBindingPath(t)\n let currentItem\n if (path) {\n if (path.substr(0,6)==':root.') {\n currentItem = getValueByPath(this.options.root, path)\n } else {\n currentItem = getValueByPath(value, path)\n }\n } else {\n currentItem = value\n }\n\n // then check the value against pattern, if set (e.g. data-bind-match=\"bar\")\n const strItem = ''+currentItem\n let matches = t.getAttribute(this.options.attribute+'-match')\n if (matches) {\n if (matches===':empty' && !currentItem) {\n return t\n } else if (matches===':notempty' && currentItem) {\n return t\n }\n if (strItem == matches) {\n return t\n }\n }\n if (!matches) {\n // no data-bind-match is set, so return this template\n return t\n }\n }\n let template = Array.from(templates).find(templateMatches)\n let links = null\n if (template?.hasAttribute(this.options.attribute+'-link')) {\n links = this.parseLinks(template.getAttribute(this.options.attribute+'-link'))\n }\n let rel = template?.getAttribute('rel')\n if (rel) {\n let replacement = document.querySelector('template#'+rel)\n if (!replacement) {\n throw new Error('Could not find template with id '+rel)\n }\n template = replacement\n }\n if (template) {\n template.links = links\n }\n return template\n }\n\n destroy()\n {\n this.bindings.forEach(binding => {\n destroy(binding)\n })\n this.bindings = new Map()\n this.observer.disconnect()\n }\n\n}\n\n/**\n * Returns a new instance of SimplyBind. This is the normal start\n * of a data bind flow\n */\nexport function bind(options)\n{\n return new SimplyBind(options)\n}\n\nconst tracking = new Map()\n\nexport function trace(path)\n{\n return tracking.get(path)\n}\n\nfunction track(el, context) {\n if (!tracking.has(context.path)) {\n tracking.set(context.path, [context])\n } else {\n tracking.get(context.path).push(context)\n }\n}\n\nfunction untrack(el, path) {\n let list = tracking.get(path)\n if (list) {\n list = list.filter(context => context.element == el)\n tracking.set(path, list)\n }\n}\n\n\n/**\n * Returns the value by walking the given path as a json pointer, starting at root\n * if you have a property with a '.' in its name urlencode the '.', e.g: %46\n * \n * @param HTMLElement root\n * @param string path e.g. 'foo.bar'\n * @return mixed the value found by walking the path from the root object or undefined\n */\nexport function getValueByPath(root, path)\n{\n let parts = path.split('.')\n let curr = root\n let part\n part = parts.shift()\n let prevPart = null\n while (part && curr) {\n part = decodeURIComponent(part)\n if (part=='0' && !Array.isArray(curr)) {\n // ignore so that data-flow-list=\"nonarray\" will work\n } else if (part==':key') {\n curr = prevPart\n } else if (part==':value') {\n // do nothing\n } else if (Array.isArray(curr) && typeof curr[part]=='undefined' && curr[0]) {\n curr = curr[0][part] // so that data-flow-field=\"array.foo\" works\n } else {\n curr = curr[part]\n }\n prevPart = part\n part = parts.shift()\n }\n return curr\n}\n", "import {signal, effect, throttledEffect, batch} from './state.mjs'\n\n/**\n * This class implements a pluggable data model, where you can\n * add effects that are run only when either an option for that\n * effect changes, or when an effect earlier in the chain of\n * effects changes.\n */\nclass SimplyFlowModel {\n\n\t/**\n\t * Creates a new datamodel, with a state property that contains\n\t * all the data passed to this constructor\n\t * @param state\tObject with all the data for this model\n\t * @throws Error if state is not set\n\t */\n\tconstructor(state) {\n\t\tif (!state) {\n\t\t\tthrow new Error('no options set')\n\t\t}\n\t\tif (state.data==null || typeof state.data[Symbol.iterator] !== 'function') {\n\t\t\tconsole.warn('SimplyFlowModel: options.data is not iterable')\n\t\t}\n\t\tthis.state = signal(state)\n\t\tif (!this.state.options) {\n\t\t\tthis.state.options = {}\n\t\t}\n\t\tthis.effects = [{current:this.state.data}]\n\t\tthis.view = {\n current: this.state.data\n }\n\t}\n\n\t/**\n\t * Adds an effect to run whenever a signal it depends on\n\t * changes. this.state is the usual signal.\n\t * The `fn` function param is not itself an effect, but must return\n\t * and effect function. `fn` takes one param, which is the data signal.\n\t * This signal will always have at least a `current` property.\n\t * The result of the effect function is pushed on to the this.effects\n\t * list. And the last effect added is set as this.view\n\t */\n\taddEffect(fn) {\n\t\tif (!fn || typeof fn !=='function') {\n\t\t\tthrow new Error('addEffect requires an effect function as its parameter', { cause: fn })\n\t\t}\n\t\tconst dataSignal = this.effects[this.effects.length-1]\n\t\tconst connectedSignal = fn.call(this, dataSignal)\n\t\tif (!connectedSignal || !connectedSignal[Symbol.Signal]) {\n\t\t\tthrow new Error('addEffect function parameter must return a Signal', { cause: fn })\n\t\t}\n\t\tthis.view = connectedSignal\n\t\tthis.effects.push(this.view)\n\t}\n}\n\nexport function model(options) {\n\treturn new SimplyFlowModel(options)\n}\n\n/**\n * Returns a function for model.addEffect that sorts the input data\n * \n * Options:\n * - direction (string) default 'asc' - change to 'desc' to sort in descending order\n * - sortBy (string) (optional) - used by the default sorting function to select the property to sort on\n * - sortFn (function) (required - set by default) - the sort function to use\n */\nexport function sort(options={}) {\n\treturn function(data) {\n\t\t// initialize the sort options, only gets called once\n\t\tthis.state.options.sort = Object.assign({\n\t\t\tdirection: 'asc',\n\t\t\tsortBy: null,\n\t\t\tsortFn: ((a,b) => {\n\t\t\t\tconst sort = this.state.options.sort\n\t\t\t\tconst sortBy = sort.sortBy\n\t\t\t\tif (!sort.sortBy) {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t\tconst larger = sort.direction == 'asc' ? 1 : -1\n\t\t\t\tconst smaller = sort.direction == 'asc' ? -1 : 1\n\t\t\t\tif (typeof a?.[sortBy] === 'undefined') {\n\t\t\t\t\tif (typeof b?.[sortBy] === 'undefined') {\n\t\t\t\t\t\treturn 0\n\t\t\t\t\t}\n\t\t\t\t\treturn larger\n\t\t\t\t}\n\t\t\t\tif (typeof b?.[sortBy] === 'undefined') {\n\t\t\t\t\treturn smaller\n\t\t\t\t}\n\t\t\t\tif (a[sortBy]<b[sortBy]) {\n\t\t\t\t\treturn smaller\n\t\t\t\t} else if (a[sortBy]>b[sortBy]) {\n\t\t\t\t\treturn larger\n\t\t\t\t} else {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t})\n\t\t}, options);\n\t\t// then return the effect, which is called when\n\t\t// either the data or the sort options change\n\t\treturn throttledEffect(() => {\n\t\t\tconst sort = this.state.options.sort\n\t\t\tif (sort?.sortBy && sort?.direction) {\n\t\t\t\treturn data.current.toSorted(sort?.sortFn)\n\t\t\t}\n\t\t\treturn data.current\n\t\t}, 50)\n\t}\n}\n\n/**\n * Returns a function for model.addEffect that implements paging\n * for the input data. It will return a slice of the data matching\n * the page and pageSize options.\n * \n * Options:\n * - page (int) default 1 - which page to show, starts at 1\n * - pageSize (int) default 20 - how many items in a single page\n * - max (int) (calculated) - how many pages in total\n */\nexport function paging(options={}) {\n\treturn function(data) {\n\t\t// initialize the paging options\n\t\tthis.state.options.paging = Object.assign({\n\t\t\tpage: 1,\n\t\t\tpageSize: 20,\n\t\t\tmax: 1\n\t\t}, options)\n\t\treturn throttledEffect(() => {\n\t\t\treturn batch(() => {\n\t\t\t\tconst paging = this.state.options.paging\n\t\t\t\tif (!paging.pageSize) {\n\t\t\t\t\tpaging.pageSize = 20\n\t\t\t\t}\n\t\t\t\tpaging.max = Math.ceil(this.state.data.length / paging.pageSize)\n\t\t\t\tpaging.page = Math.max(1, Math.min(paging.max, paging.page))\n\n\t\t\t\tconst start = (paging.page-1) * paging.pageSize\n\t\t\t\tconst end = start + paging.pageSize\n\t\t\t\treturn data.current.slice(start, end)\n\t\t\t})\n\t\t}, 50)\n\t}\n}\n\n/**\n * Returns a function for model.addEffect that filters rows from the data,\n * using a custom filter function `options.matches`\n * \n * Options:\n * - name (string) (required) - the name of this filter, must be unique\n * - matches (function) (required) - the filter function to apply to the data\n * - enabled (bool) (required) - filter is applied only when enabled is set to true\n */\nexport function filter(options) {\n\tif (!options?.name || typeof options.name!=='string') {\n\t\tthrow new Error('filter requires options.name to be a string')\n\t}\n\tif (!options.matches || typeof options.matches!=='function') {\n\t\tthrow new Error('filter requires options.matches to be a function')\n\t}\n\treturn function(data) {\n\t\tif (this.state.options[options.name]) {\n\t\t\tthrow new Error('a filter with this name already exists on this model')\n\t\t}\n\t\tthis.state.options[options.name] = options\n\t\treturn throttledEffect(() => {\n\t\t\tif (this.state.options[options.name].enabled) {\n\t\t\t\treturn data.current.filter(this.state.options[options.name].matches.bind(this))\n\t\t\t}\n\t\t\treturn data.current\n\t\t}, 50)\n\t}\n}\n\n/**\n * Returns a function for model.addEffect that filters the data to only contain\n * columns (properties) that aren't hidden. Automatically runs again if any columns\n * hidden property changes.\n * \n * Options:\n * - columns (object) (required) - an object with properties describing each column. Each \n * property must be an object with an optional `hidden` property. If set to a truthy value,\n * and property in the dataset with the same name, will be filtered out.\n */\nexport function columns(options={}) {\n\tif (!options\n\t\t|| typeof options!=='object'\n\t\t|| Object.keys(options).length===0) {\n\t\tthrow new Error('columns requires options to be an object with at least one property')\n\t}\n\treturn function(data) {\n\t\tthis.state.options.columns = options\n\t\treturn throttledEffect(() => {\n\t\t\treturn data.current.map(input => {\n\t\t\t\tlet result = {}\n\t\t\t\tfor (let key of Object.keys(this.state.options.columns)) {\n\t\t\t\t\tif (!this.state.options.columns[key]?.hidden) {\n\t\t\t\t\t\tresult[key] = input[key] ?? null\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t})\n\t\t}, 50)\n\t}\n}\n\n/**\n * Returns a function for use with model.addEffect, with the given options set\n * as model.options.scroll. The effect will return a slice of the input data, which\n * makes it easy to render just a part (slice) of the whole data.\n * \n * Options are:\n * - offset (int) default 0 (optional) - the offset in the data to start the slice\n * - rowCount (int) default 20 (optional / calculated) - the number of rows in the slice\n * - rowHeight (int) default 26 (optional) - the height of a single row in pixels\n * - itemsPerRow (int) default 1 (optional) - the number of items on a single row\n * - size (int) default data.current.length (calculated) - how many rows inside data.current before slicing\n * - scrollbar (HTMLElement) defualt null (optional) - if set, an effect is added to update this elements \n * \t height if data.current.length changes\n * - container (HTMLElement) default null (optional) - if set, a scroll listener is added to this element, \n * which will update the options.offset signal and trigger the slice effect. It will also set the rowCount.\n */\nexport function scroll(options) {\n\n\treturn function(data) {\n\t\tthis.state.options.scroll = Object.assign({\n\t\t\toffset: 0,\n\t\t\trowHeight: 26,\n\t\t\trowCount: 20,\n\t\t\titemsPerRow: 1,\n\t\t\tsize: data.current.length\n\t\t}, options)\n\t\tconst scrollOptions = this.state.options.scroll\n\n\t\tconst scrollbar = scrollOptions.scrollbar \n\t\t\t|| scrollOptions.container?.querySelector('[data-flow-scrollbar]')\n\t\tif (scrollbar) {\n\t\t\tif (scrollOptions.container) {\n\t\t\t\tscrollOptions.container.addEventListener('scroll', (evt) => {\n\t\t\t\t\tscrollOptions.offset = Math.floor(scrollOptions.container.scrollTop\n\t\t\t\t\t\t/ (scrollOptions.rowHeight*scrollOptions.itemsPerRow)\n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tthrottledEffect(() => {\n\t\t\t\tscrollOptions.size = data.current.length * scrollOptions.rowHeight\n\t\t\t\tscrollbar.style.height = scrollOptions.size + 'px'\n\t\t\t}, 50)\n\t\t}\n\n\t\treturn throttledEffect(() => {\n\t\t\tif (scrollOptions.container) {\n\t\t\t\t//TODO: add a resize listener so that if the size of the container\n\t\t\t\t// changes, the rowCount is calculated again\n\t\t\t\tscrollOptions.rowCount = Math.ceil(\n\t\t\t\t\tscrollOptions.container.getBoundingClientRect().height \n\t\t\t\t\t/ scrollOptions.rowHeight\n\t\t\t\t)\n\t\t\t}\n\t\t\tscrollOptions.data = data.current\n\t\t\tlet start = Math.min(scrollOptions.offset, data.current.length-1)\n\t\t\tlet end = start + scrollOptions.rowCount\n\t\t\tif (end > data.current.length) {\n\t\t\t\tend = data.current.length\n\t\t\t\tstart = end - scrollOptions.rowCount\n\t\t\t}\n\t\t\treturn data.current.slice(start, end)\n\t\t}, 50)\n\t}\n}", "export class SimplyRender extends HTMLElement \n{\n constructor()\n {\n super()\n }\n\n connectedCallback()\n {\n let templateId = this.getAttribute(\"rel\")\n let template = document.getElementById(templateId)\n\n if (template) {\n let content = template.content.cloneNode(true)\n for (const node of content.childNodes) {\n const clone = node.cloneNode(true)\n if (clone.nodeType == document.ELEMENT_NODE) {\n clone.querySelectorAll(\"template\").forEach(function(t) {\n t.setAttribute(\"simply-render\", \"\") //FIXME: whats this?\n })\n if (this.attributes) {\n for (const attr of this.attributes) {\n if (attr.name!='rel') {\n clone.setAttribute(attr.name, attr.value)\n }\n }\n }\n }\n this.parentNode.insertBefore(clone, this)\n }\n this.parentNode.removeChild(this)\n } else {\n const observe = () => {\n const observer = new MutationObserver(() => {\n template = document.getElementById(templateId)\n if (template) {\n observer.disconnect()\n this.replaceWith(this) // trigger connectedCallback?\n }\n })\n observer.observe(globalThis.document, {\n subtree: true,\n childList: true,\n })\n }\n\n observe()\n }\n }\n}\n\nif (!customElements.get('simply-render')) {\n customElements.define('simply-render', SimplyRender);\n}", "import { bind } from './bind.mjs'\nimport * as model from './model.mjs'\nimport * as state from './state.mjs'\nimport './render.mjs'\nimport * as dom from './dom.mjs'\n\nif (!globalThis.simply) {\n\tglobalThis.simply = {}\n}\nObject.assign(globalThis.simply, {\n\tbind,\n\tflow: model,\n\tstate,\n\tdom\n})\n\nexport default globalThis.simply"],
5
- "mappings": "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",
6
- "names": ["state_exports", "__export", "addTracer", "batch", "clockEffect", "clone", "destroy", "effect", "makeContext", "notifyGet", "notifySet", "signal", "signals", "throttledEffect", "trace", "untracked", "signalHandler", "target", "property", "receiver", "value", "args", "l", "result", "current", "descriptor", "v", "tracers", "tracing", "prop", "getListeners", "listener", "tracer", "callTracers", "getset", "params", "batchedListeners", "batchMode", "self", "context", "listeners", "change", "propListeners", "addContext", "currentEffect", "computeStack", "clearContext", "currentCompute", "setListeners", "listenersMap", "computeMap", "compute", "connectedSignals", "clearListeners", "s", "effectStack", "effectMap", "signalStack", "fn", "f", "connectedSignal", "computeEffect", "runBatchedListeners", "copyBatchedListeners", "throttleTime", "throttled", "hasChange", "clock", "lastTick", "hasChanged", "pos", "remember", "deep", "seen", "innerClone", "key", "escape_html", "context", "next", "content", "fixed_content", "dom_exports", "__export", "signal", "domSignalHandler", "target", "property", "receiver", "value", "notifyGet", "signal", "signals", "el", "options", "domListen", "observers", "oldContentHTML", "oldContentText", "observer", "mutationList", "changes", "mutation", "prop", "notifySet", "makeContext", "prevValue", "evt", "field", "context", "fieldByTemplates", "renderer", "list", "length", "arrayByTemplates", "map", "objectByTemplates", "isInt", "s", "setValueByPath", "root", "path", "value", "batch", "parts", "curr", "part", "prev", "prevPart", "prevCurr", "intKey", "prop", "attribute", "items", "lastKey", "skipped", "item", "currentKey", "bindings", "needsReplacement", "b", "databind", "newTemplate", "signal", "throttledEffect", "children", "untracked", "key", "currentList", "source", "getValueByPath", "clone", "outOfOrderItem", "i", "rendered", "template", "getParentPath", "el", "parentEl", "input", "element", "matchValue", "button", "select", "option", "o", "setSelectOptions", "setProperties", "addOption", "options", "anchor", "updateProperties", "image", "iframe", "meta", "domSignals", "extraprops", "valueIsString", "strValue", "props", "updateValue", "getProperties", "data", "properties", "property", "result", "a", "SimplyBind", "options", "defaultTransformers", "escape_html", "fixed_content", "defaultOptions", "field", "list", "map", "input", "button", "select", "anchor", "image", "iframe", "meta", "element", "attribute", "bindAttributes", "transformAttribute", "getBindingAttribute", "el", "foundAttribute", "attr", "renderElement", "throttledEffect", "untrack", "destroy", "context", "getValueByPath", "track", "runTransformers", "transformers", "t", "next", "transformer", "applyBindings", "bindings", "bindingEl", "updateBindings", "changes", "selector", "change", "node", "path", "parent", "templates", "index", "value", "template", "result", "clone", "attributes", "binding", "bind", "links", "link", "templateMatches", "currentItem", "strItem", "matches", "rel", "replacement", "tracking", "track", "el", "context", "tracking", "untrack", "path", "list", "getValueByPath", "root", "parts", "curr", "part", "prevPart", "model_exports", "__export", "columns", "filter", "model", "paging", "scroll", "sort", "SimplyFlowModel", "state", "signal", "fn", "dataSignal", "connectedSignal", "model", "options", "sort", "data", "a", "b", "sortBy", "larger", "smaller", "throttledEffect", "paging", "batch", "start", "end", "filter", "columns", "input", "result", "key", "scroll", "scrollOptions", "scrollbar", "evt", "SimplyRender", "templateId", "template", "content", "node", "clone", "t", "attr", "observer", "bind", "model_exports", "state_exports", "dom_exports", "flow_default"]
4
+ "sourcesContent": ["if (!Symbol.iterate) {\n Symbol.iterate = Symbol('iterate')\n}\nif (!Symbol.xRay) {\n Symbol.xRay = Symbol('xRay')\n}\nif (!Symbol.Signal) {\n Symbol.Signal = Symbol('Signal')\n}\n\nconst signalHandler = {\n get: (target, property, receiver) => {\n if (property===Symbol.xRay) {\n return target // don't notifyGet here, this is only called by set\n }\n if (property===Symbol.Signal) {\n return true\n }\n const value = target?.[property] // Reflect.get fails on a Set.\n notifyGet(receiver, property)\n if (typeof value === 'function') {\n if (Array.isArray(target)) {\n return (...args) => {\n let l = target.length\n // by binding the function to the receiver\n // all accesses in the function will be trapped\n // by the Proxy, so get/set/delete is all handled\n let result = value.apply(receiver, args)\n if (l != target.length) {\n notifySet(receiver, makeContext('length', { was: l, now: target.length }) )\n }\n return result\n }\n } else if (target instanceof Set || target instanceof Map) {\n return (...args) => {\n // node doesn't allow you to call set/map functions\n // bound to the receiver.. so using target instead\n // there are no properties to update anyway, except for size\n let s = target.size\n let result = value.apply(target, args)\n if (s != target.size) {\n notifySet(receiver, makeContext( 'size', { was: s, now: target.size }) )\n }\n // there is no efficient way to see if the function called\n // has actually changed the Set/Map, but by assuming the\n // 'setter' functions will change the results of the\n // 'getter' functions, effects should update correctly\n if (['set','add','clear','delete'].includes(property)) {\n notifySet(receiver, makeContext( { entries: {}, forEach: {}, has: {}, keys: {}, values: {}, [Symbol.iterator]: {} } ) )\n }\n return result\n }\n } else if (\n target instanceof HTMLElement\n || target instanceof Number\n || target instanceof String\n || target instanceof Boolean\n ) {\n return value.bind(target)\n } else {\n // support custom classes, hopefully\n return value.bind(receiver)\n }\n }\n if (value && typeof value == 'object') {\n return signal(value)\n }\n return value\n },\n set: (target, property, value, receiver) => {\n let current = target[property]\n if (current!==value) {\n target[property] = value\n notifySet(receiver, makeContext(property, { was: current, now: value } ) )\n }\n if (typeof current === 'undefined') {\n notifySet(receiver, makeContext(Symbol.iterate, {}))\n notifySet(receiver, makeContext('length', {}))\n }\n return true\n },\n has: (target, property) => { // receiver is not part of the has() call\n let receiver = signals.get(target) // so retrieve it here\n if (receiver) {\n notifyGet(receiver, property)\n }\n return Object.hasOwn(target, property)\n },\n deleteProperty: (target, property) => {\n if (typeof target[property] !== 'undefined') {\n let current = target[property]\n delete target[property]\n let receiver = signals.get(target) // receiver is not part of the trap arguments, so retrieve it here\n notifySet(receiver, makeContext(property,{ delete: true, was: current }))\n }\n return true\n },\n defineProperty: (target, property, descriptor) => {\n if (typeof target[property] === 'undefined') {\n let receiver = signals.get(target) // receiver is not part of the trap arguments, so retrieve it here\n notifySet(receiver, makeContext(Symbol.iterate, {}))\n }\n return Object.defineProperty(target, property, descriptor)\n },\n ownKeys: (target) => {\n let receiver = signals.get(target) // receiver is not part of the trap arguments, so retrieve it here\n notifyGet(receiver, Symbol.iterate)\n return Reflect.ownKeys(target)\n }\n\n}\n\n/**\n * Keeps track of the return signal for an update function, as well\n * as signals connected to other objects. \n * Makes sure that a given object or function always uses the same\n * signal\n */\nexport const signals = new WeakMap()\n\n/**\n * Creates a new signal proxy of the given object, that intercepts get/has and set/delete\n * to allow reactive functions to be triggered when signal values change.\n */\nexport function signal(v) {\n if (!v) {\n v = {}\n }\n if (v[Symbol.Signal]) { // there can be only one signal for any value\n return v\n }\n if (!signals.has(v)) {\n signals.set(v, new Proxy(v, signalHandler))\n }\n return signals.get(v)\n}\n\n\nlet tracers = []\nlet tracing = false\n/**\n * @param Signal|Function signal\n * If given a singal and property, this function lists all effects \n * that are currently listening to changes to that signal and property\n * returns a list with \n * - effect: the effect function (effect, throttledEffect, clockEffect)\n * - fn: the user provided function to this effect function\n * - signal: the connectedSignal to this user provided function\n * @param string prop \n * @return array of { effect, fn, signal }\n * \n * If given a function, it will enable any tracers added with addTracer\n * call the given function and then disable all tracers.\n * @return void\n */\nexport function trace(signal, prop) {\n if (typeof signal==='function') {\n tracing = true\n signal()\n tracing = false\n } else {\n const listeners = getListeners(signal, prop)\n return listeners.map(listener => {\n return {\n effect: listener.effectType,\n fn: listener.effectFunction,\n signal: signals.get(listener.effectFunction)\n }\n })\n }\n}\n\n/**\n * Adds a tracer. This is an object with a 'set' and/or 'get' function.\n * If enabled (with the trace() method) each access to notifyGet will \n * call the 'get' function. Each access to notifySet will call the 'set'\n * function.\n * @param tracer { get: fn, set: fn }\n * get: function(signal, property)\n * set: function(signal, context, listener)\n */\nexport function addTracer(tracer) {\n if (!tracer.get && !tracer.set) {\n throw new Error('simply.state: addTracer: missing \"get\" or \"set\" property in tracer', tracer)\n }\n if (tracer.get && typeof tracer.get!=='function') {\n throw new Error('simply.state: addTracer: \"get\" is not a function', tracer)\n }\n if (tracer.set && typeof tracer.set!=='function') {\n throw new Error('simply.state: addTracer: \"set\" is not a function', tracer)\n }\n tracers.push(tracer)\n}\n\nfunction callTracers(getset, ...params) {\n for (const tracer of tracers) {\n if (tracer[getset]) {\n tracer[getset](...params)\n }\n }\n}\n\nlet batchedListeners = new Set()\nlet batchMode = 0\n/**\n * Called when a signal changes a property (set/delete)\n * Triggers any reactor function that depends on this signal\n * to re-compute its values\n */\nexport function notifySet(self, context={}) {\n let listeners = []\n context.forEach((change, property) => {\n let propListeners = getListeners(self, property)\n if (propListeners?.length) {\n for (let listener of propListeners) {\n addContext(listener, makeContext(property,change))\n }\n listeners = listeners.concat(propListeners)\n }\n })\n listeners = new Set(listeners.filter(Boolean))\n if (listeners) {\n if (batchMode) {\n batchedListeners = batchedListeners.union(listeners)\n } else {\n const currentEffect = computeStack[computeStack.length-1]\n for (let listener of Array.from(listeners)) {\n if (listener!=currentEffect && listener?.needsUpdate) {\n if (tracing && tracers.length) {\n callTracers('set', self, context, listener)\n }\n listener()\n }\n clearContext(listener)\n }\n }\n }\n}\n\n\nexport function makeContext(property, change) {\n let context = new Map()\n if (typeof property === 'object') {\n for (let prop in property) {\n context.set(prop, property[prop])\n }\n } else {\n context.set(property, change)\n }\n return context\n}\n\nfunction addContext(listener, context) {\n if (!listener.context) {\n listener.context = context\n } else {\n context.forEach((change,property)=> {\n listener.context.set(property, change) // TODO: merge change if needed\n })\n }\n listener.needsUpdate = true\n}\n\nfunction clearContext(listener) {\n delete listener.context\n delete listener.needsUpdate\n}\n\n/**\n * Called when a signal property is accessed. If this happens\n * inside a reactor function--computeStack is not empty--\n * then it adds the current reactor (top of this stack) to its\n * listeners. These are later called if this property changes\n */\nexport function notifyGet(self, property) {\n let currentCompute = computeStack[computeStack.length-1]\n if (currentCompute) {\n if (tracing && tracers.length) {\n callTracers('get', self, property)\n }\n // get was part of a react() function, so add it\n setListeners(self, property, currentCompute)\n }\n}\n\n/**\n * Keeps track of which update() functions are dependent on which\n * signal objects and which properties. Maps signals to update fns\n */\nconst listenersMap = new WeakMap()\n\n/**\n * Keeps track of which signals and properties are linked to which\n * update functions. Maps update functions and properties to signals\n */\nconst computeMap = new WeakMap()\n\n/**\n * Returns the update functions for a given signal and property\n */\nfunction getListeners(self, property) {\n let listeners = listenersMap.get(self)\n return listeners ? Array.from(listeners.get(property) || []) : []\n}\n\n/**\n * Adds an update function (compute) to the list of listeners on\n * the given signal (self) and property\n */\nfunction setListeners(self, property, compute) {\n if (!listenersMap.has(self)) {\n listenersMap.set(self, new Map())\n }\n let listeners = listenersMap.get(self)\n if (!listeners.has(property)) {\n listeners.set(property, new Set())\n }\n listeners.get(property).add(compute)\n\n if (!computeMap.has(compute)) {\n computeMap.set(compute, new Map())\n }\n let connectedSignals = computeMap.get(compute)\n if (!connectedSignals.has(property)) {\n connectedSignals.set(property, new Set)\n }\n connectedSignals.get(property).add(self)\n}\n\n/**\n * Removes alle listeners that trigger the given reactor function (compute)\n * This happens when a reactor is called, so that it can set new listeners\n * based on the current call (code path)\n */\nfunction clearListeners(compute) {\n let connectedSignals = computeMap.get(compute)\n if (connectedSignals) {\n connectedSignals.forEach(property => {\n property.forEach(s => {\n let listeners = listenersMap.get(s)\n if (listeners.has(property)) {\n listeners.get(property).delete(compute)\n }\n })\n })\n }\n}\n\n/**\n * The top most entry is the currently running update function, used\n * to automatically record signals used in an update function.\n */\nlet computeStack = []\n\n/**\n * Used for cycle detection: effectStack contains all running effect\n * functions. If the same function appears twice in this stack, there\n * is a recursive update call, which would cause an infinite loop.\n */\nconst effectStack = []\n\nconst effectMap = new WeakMap()\n/**\n * Used for cycle detection: signalStack contains all used signals. \n * If the same signal appears more than once, there is a cyclical \n * dependency between signals, which would cause an infinite loop.\n */\nconst signalStack = []\n\n/**\n * Runs the given function at once, and then whenever a signal changes that\n * is used by the given function (or at least signals used in the previous run).\n */\nexport function effect(fn) {\n if (effectStack.findIndex(f => fn==f)!==-1) {\n throw new Error('Recursive update() call', {cause:fn})\n }\n effectStack.push(fn)\n\n let connectedSignal = signals.get(fn)\n if (!connectedSignal) {\n connectedSignal = signal({\n current: null\n })\n signals.set(fn, connectedSignal)\n }\n\n // this is the function that is called automatically\n // whenever a signal dependency changes\n const computeEffect = function computeEffect() {\n if (signalStack.findIndex(s => s==connectedSignal)!==-1) {\n throw new Error('Cyclical dependency in update() call', { cause: fn})\n }\n // remove all dependencies (signals) from previous runs \n clearListeners(computeEffect)\n computeEffect.effectFunction = fn\n computeEffect.effectType = effect\n // record new dependencies on this run\n computeStack.push(computeEffect)\n // prevent recursion\n signalStack.push(connectedSignal)\n // call the actual update function\n let result\n try {\n result = fn(computeEffect, computeStack, signalStack)\n } finally {\n // stop recording dependencies\n computeStack.pop()\n // stop the recursion prevention\n signalStack.pop()\n if (result instanceof Promise) {\n result.then((result) => {\n connectedSignal.current = result\n })\n } else {\n connectedSignal.current = result\n }\n }\n }\n computeEffect.fn = fn\n effectMap.set(connectedSignal, computeEffect)\n\n // run the computEffect immediately upon creation\n computeEffect()\n return connectedSignal\n}\n\n\nexport function destroy(connectedSignal) {\n // find the computeEffect associated with this signal\n const computeEffect = effectMap.get(connectedSignal)?.deref()\n if (!computeEffect) {\n return\n }\n\n // remove all listeners for this effect\n clearListeners(computeEffect)\n\n // remove all references to connectedSignal\n let fn = computeEffect.fn\n signals.remove(fn)\n\n effectMap.delete(connectedSignal)\n\n // if no other references to connectedSignal exist, it will be garbage collected\n}\n\n/**\n * Inside a batch() call, any changes to signals do not trigger effects\n * immediately. Instead, immediately after finishing the batch() call,\n * these effects will be called. Effects that are triggered by multiple\n * signals are called only once.\n * @param Function fn batch() calls this function immediately\n * @result mixed the result of the fn() function call\n */\nexport function batch(fn) {\n batchMode++\n let result\n try {\n result = fn()\n } finally {\n if (result instanceof Promise) {\n result.then(() => {\n batchMode--\n if (!batchMode) {\n runBatchedListeners()\n }\n })\n } else {\n batchMode--\n if (!batchMode) {\n runBatchedListeners()\n }\n }\n }\n return result\n}\n\nfunction runBatchedListeners() {\n let copyBatchedListeners = Array.from(batchedListeners)\n batchedListeners = new Set()\n const currentEffect = computeStack[computeStack.length-1]\n for (let listener of copyBatchedListeners) {\n if (listener!=currentEffect && listener?.needsUpdate) {\n listener()\n }\n clearContext(listener)\n }\n}\n\n/**\n * A throttledEffect is run immediately once. And then only once\n * per throttleTime (in ms).\n * @param Function fn the effect function to run whenever a signal changes\n * @param int throttleTime in ms\n * @returns signal with the result of the effect function fn\n */\nexport function throttledEffect(fn, throttleTime) {\n if (effectStack.findIndex(f => fn==f)!==-1) {\n throw new Error('Recursive update() call', {cause:fn})\n }\n effectStack.push(fn)\n\n let connectedSignal = signals.get(fn)\n if (!connectedSignal) {\n connectedSignal = signal({\n current: null\n })\n signals.set(fn, connectedSignal)\n }\n\n let throttled = false\n let hasChange = true\n // this is the function that is called automatically\n // whenever a signal dependency changes\n const computeEffect = function computeEffect() {\n if (signalStack.findIndex(s => s==connectedSignal)!==-1) {\n throw new Error('Cyclical dependency in update() call', { cause: fn})\n }\n if (throttled && throttled>Date.now()) {\n hasChange = true\n return\n }\n // remove all dependencies (signals) from previous runs \n clearListeners(computeEffect)\n // record new dependencies on this run\n computeEffect.effectFunction = fn\n computeEffect.effectType = throttledEffect\n computeStack.push(computeEffect)\n // prevent recursion\n signalStack.push(connectedSignal)\n // call the actual update function\n let result\n try {\n result = fn(computeEffect, computeStack, signalStack)\n } finally {\n hasChange = false\n // stop recording dependencies\n computeStack.pop()\n // stop the recursion prevention\n signalStack.pop()\n if (result instanceof Promise) {\n result.then((result) => {\n connectedSignal.current = result\n })\n } else {\n connectedSignal.current = result\n }\n }\n throttled = Date.now()+throttleTime\n globalThis.setTimeout(() => {\n if (hasChange) {\n computeEffect()\n }\n }, throttleTime)\n }\n // run the computEffect immediately upon creation\n computeEffect()\n return connectedSignal\n}\n\n// refactor: Class clock() with an effect() method\n// keep track of effects per clock, and add clock property to the effect function\n// on notifySet add clock.effects to clock.needsUpdate list\n// on clock.tick() (or clock.time++) run only the clock.needsUpdate effects \n// (first create a copy and reset clock.needsUpdate, then run effects)\nexport function clockEffect(fn, clock) {\n let connectedSignal = signals.get(fn)\n if (!connectedSignal) {\n connectedSignal = signal({\n current: null\n })\n signals.set(fn, connectedSignal)\n }\n\n let lastTick = -1 // clock.time should start at 0 or larger\n let hasChanged = true // make sure the first run goes through\n // this is the function that is called automatically\n // whenever a signal dependency changes\n const computeEffect = function computeEffect() {\n if (lastTick < clock.time) {\n if (hasChanged) {\n // remove all dependencies (signals) from previous runs \n clearListeners(computeEffect)\n computeEffect.effectFunction = fn\n computeEffect.effectType = clockEffect\n // record new dependencies on this run\n computeStack.push(computeEffect)\n // make sure the clock.time signal is a dependency\n lastTick = clock.time\n // call the actual update function\n let result \n try {\n result = fn(computeEffect, computeStack)\n } finally {\n // stop recording dependencies\n computeStack.pop()\n if (result instanceof Promise) {\n result.then((result) => {\n connectedSignal.current = result\n })\n } else {\n connectedSignal.current = result\n }\n hasChanged = false\n }\n } else {\n lastTick = clock.time\n }\n } else {\n hasChanged = true\n }\n }\n // run the computEffect immediately upon creation\n computeEffect()\n return connectedSignal\n}\n\n/**\n * Any signal access inside `fn` is not tracked for the current effect.\n * Any changes to signals inside `fn` will still trigger any effect listening to thoses signals.\n * @param fn Function that is called immediately. Its result is returned.\n * @result mixed\n */\nexport function untracked(fn) {\n const pos = computeStack.length-1\n const remember = computeStack[pos]\n computeStack[pos] = false\n try {\n return fn()\n } finally {\n computeStack[pos] = remember\n }\n}\n\n/**\n * This function will created a copy of the input, recursive if deep==true\n * It will replace any non-clonable values with null\n * It will replace signals with a clone of their target\n * It will keep cyclical references intact\n * @param value Object\n * @param deep Boolean default: false\n * @return mixed a clone of the value\n */\nexport function clone(value, deep=false)\n{\n let seen = new Map()\n const innerClone = function(value) {\n if (seen.has(value)) {\n return seen.get(value)\n }\n switch(typeof value) {\n case 'object':\n if (!value) {\n return value\n }\n if (Array.isArray(value)) {\n let result = []\n if (!deep) {\n result = value.slice()\n seen.set(value, result)\n return result\n }\n seen.set(value, result)\n for (const key of value) {\n result[key] = innerClone(value[key])\n }\n } else if (!value.constructor || value.constructor===Object) {\n let result = {}\n if (!value.constructor) {\n result = Object.create(null)\n }\n seen.set(value, result)\n for (const key in value) {\n result[key] = deep ? innerClone(value[key]) : value[key]\n }\n return result\n } else {\n // cannot clone, ignore? throw error?\n return value\n }\n break\n default:\n return null // ignore non-cloneable values\n break\n }\n }\n return innerClone(value)\n}", "export function escape_html(context, next) {\n let content = context.value?.innerHTML\n if (typeof context.value == 'string') {\n content = context.value\n context.value = { innerHTML: content }\n }\n if (content) {\n content = content.replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n context.value.innerHTML = content\n }\n next(context)\n}\n\nexport function fixed_content(context, next) {\n if (typeof context.value == 'string') {\n context.value = {}\n } else {\n delete context.value?.innerHTML\n }\n next(context)\n}\n", "import { signals, signal as stateSignal, notifyGet, notifySet, makeContext,\n throttledEffect, effect, untracked, batch } from './state.mjs'\nimport { getValueByPath } from './bind.mjs'\nimport { setValueByPath, getProperties } from './bind.render.mjs'\n\nconst domSignals = new WeakMap()\n\nconst domSignalHandler = {\n get: (target, property, receiver) => {\n if (property===Symbol.xRay) {\n return target // don't notifyGet here, this is only called by set\n }\n if (property===Symbol.Signal) {\n return true\n }\n const value = target?.[property]\n notifyGet(receiver, property)\n if (typeof value === 'function') {\n return value.bind(target) // make sure element functions are not linked to the proxy\n }\n if (value && typeof value == 'object') {\n return stateSignal(value)\n }\n return value\n },\n has: (target, property) => {\n let receiver = signals.get(target)\n if (receiver) {\n notifyGet(receiver, property)\n }\n return Object.hasOwn(target, property)\n },\n ownKeys: (target) => {\n let receiver = signals.get(target) // receiver is not part of the trap arguments, so retrieve it here\n if (receiver) {\n notifyGet(receiver, iterate)\n }\n return Reflect.ownKeys(target)\n }\n}\n\nexport function signal(el, options) {\n if (el[Symbol.xRay]) {\n return el\n }\n if (!signals.has(el)) {\n signals.set(el, new Proxy(el, domSignalHandler))\n domListen(el, signals.get(el), options)\n }\n return signals.get(el)\n}\n\nconst observers = new WeakMap()\n\nfunction domListen(el, signal, options) {\n const defaultOptions = {\n characterData: true,\n subtree: true,\n attributes: true,\n attributesOldValue: true\n }\n if (!options) {\n options = defaultOptions\n }\n let oldContentHTML = el.innerHTML\n let oldContentText = el.innerText\n if (!observers.has(el)) {\n const observer = new MutationObserver((mutationList, observer) => {\n // collect changes\n const changes = {}\n for (const mutation of mutationList) {\n if (mutation.type==='attributes') {\n // check if any listeners for each attribute\n changes[mutation.attributeName] = mutation.attributeOldValue\n } else if (mutation.type==='subtree' || mutation.type==='characterData') {\n // change on innerHTML/innerText\n if (el.innerHTML != oldContentHTML) {\n changes.innerHTML = oldContentHTML\n oldContentHTML = el.innerHTML\n }\n if (el.innerText != oldContentText) {\n changes.innerText = oldContentText\n oldContentText = el.innerText\n }\n } else if (mutation.type==='childList') {\n changes.children = { //FIXME: overwrites changes in this list path if list is rendered multiple times\n was: Array.from(el.children) //FIXME; fill in 'now'\n }\n changes.length = -1 //FIXME: don't do this :)\n } else {\n console.log('nothing to do for',el,mutation.type)\n }\n }\n for (const prop in changes) {\n notifySet(signal, makeContext(prop, { was: changes[prop], now: el[prop] }))\n }\n })\n observer.observe(el, options)\n observers.set(el, observer)\n //@TODO: unregister the observer when el is removed from the dom (after a timeout)\n if (el.matches('input, textarea, select')) {\n let prevValue = el.value\n el.addEventListener('change', (evt) => {\n notifySet(signal, makeContext('value', { was: prevValue, now: el.value }))\n prevValue = el.value\n })\n if (el.matches('input, textarea')) {\n el.addEventListener('input', (evt) => {\n notifySet(signal, makeContext('value', { was: prevValue, now: el.value }))\n prevValue = el.value\n })\n }\n }\n }\n}\n\nexport function trackDomList(element)\n{\n const path = this.getBindingPath(element)\n if (!path) {\n throw new Error('Could not find binding path for element', { cause: element })\n }\n const s = signal(element, {\n childList: true\n })\n throttledEffect(() => {\n const children = Array.from(s.children)\n untracked(() => { // don't track access to the data, only track dom changes\n batch(() => { // apply all changes in the list as one change\n let key=0\n const currentList = getValueByPath(this.options.root, path)\n const source = currentList.slice() // make sure changes in currentList don't affect the original source\n for (const item of children) {\n if (item.tagName==='TEMPLATE') {\n continue\n }\n if (item.dataset.flowKey) { //FIXME: could be other attribute name\n if (item.dataset.flowKey!=key) {\n setValueByPath(this.options.root, path+'.'+key,\n source[item.dataset.flowKey])\n }\n key++\n }\n }\n if (currentList.length>key) {\n // remove extra values\n currentList.length = key\n }\n })\n })\n })\n}\n\nexport function trackDomField(element, props, valueIsString) {\n if (domSignals.has(element)) {\n return\n }\n const path = this.getBindingPath(element)\n if (!path) {\n throw new Error('Could not find binding path for element', { cause: element })\n }\n const s = signal(element)\n domSignals.set(element, s)\n //TODO: run reverse transformers (extract)\n batch(() => { // avoids cyclical dependencies - check why\n throttledEffect(() => {\n let updateValue = s.innerHTML //FIXME: incorrect: in an anchor this could be s.href - use extract here\n if (!valueIsString) {\n updateValue = getProperties(s, ...props)\n }\n untracked(() => { // don't track changes in data, only in the dom\n // don't trigger this effect when the data changes (root.path)\n setValueByPath(this.options.root, path, updateValue)\n })\n })\n })\n}", "/*\n * Default renderers for data binding\n * Will be used unless overriden in the SimplyBind options parameter\n */\nimport { signal as domSignal, trackDomField, trackDomList } from './dom.mjs'\nimport { throttledEffect, effect, untracked, batch } from './state.mjs'\nimport { getValueByPath } from './bind.mjs'\n/**\n * This function is used by default to render dom elements with the `data-flow-field` attribute.\n * It will switch to only switching in template content if the context has any templates.\n * Otherwise it will call the matching render function depending on the tagName of the\n * context.element\n */\nexport function field(context)\n{\n if (context.templates?.length) {\n fieldByTemplates.call(this, context)\n // TODO: check if existence of one or more templates must mean that\n // only the template rendering is applied, instead of also rendering attributes\n } else if (Object.hasOwnProperty.call(this.options.renderers, context.element.tagName)) {\n const renderer = this.options.renderers[context.element.tagName]\n if (renderer) {\n renderer.call(this, context)\n }\n } else if (this.options.renderers['*']) {\n this.options.renderers['*'].call(this, context)\n }\n return context\n}\n\n/**\n * This function is used by default to render DOM elements with the `data-flow-list` attribute.\n * The context.value must be an array. And context.templates must not be empty.\n */\nexport function list(context)\n{\n if (!Array.isArray(context.value)) {\n context.value = [context.value]\n }\n // make sure this effect is triggered if the length of the array changes\n const length = context.value.length\n if (!context.templates?.length) {\n console.error('No templates found in', context.element)\n } else {\n arrayByTemplates.call(this, context)\n }\n return context\n}\n\n/**\n * This function is used by default to render DOM elements with the `data-flow-map` attribute.\n * The context.value must be a non-null object. And context.templates must not be empty.\n */\nexport function map(context)\n{\n if (typeof context.value != 'object' || !context.value) {\n console.error('Value is not an object.', context.element, context.path, context.value)\n } else if (!context.templates?.length) {\n console.error('No templates found in', context.element)\n } else {\n objectByTemplates.call(this, context)\n }\n return context\n}\n\nfunction isInt(s) {\n if (parseInt(s)==s) {\n return true\n }\n}\n\n/**\n * This function sets a given value on the given path, starting at the given root.\n * It will automatically create objects if a path part does not yet exist.\n * @param root the root object\n * @param path a JSON path\n * @param value the value to set\n */\nexport function setValueByPath(root, path, value)\n{\n batch(() => {\n let parts = path.split('.')\n let curr = root\n let part\n part = parts.shift()\n let prev = null\n let prevPart = null\n let prevCurr = curr\n while (part && curr) {\n prevCurr = curr\n part = decodeURIComponent(part)\n if (part=='0' && !Array.isArray(curr)) {\n // ignore so that data-flow-list=\"nonarray\" will work\n } else if (part==':key') {\n // FIXME: should change the key, not the value... not supported yet?\n throw new Error('setting key not yet supported')\n curr = prevPart\n } else if (part==':value') {\n // do nothing\n } else if (Array.isArray(curr) && !isInt(part) && typeof curr[part]=='undefined') {\n prev = curr[0]\n curr = curr[0][part] // so that data-flow-field=\"array.foo\" works\n } else {\n prev = curr\n curr = curr[part]\n }\n prevPart = part\n part = parts.shift()\n if (part && !curr) {\n // path in html does not exist yet, so create it\n const intKey = parseInt(part)\n if (intKey>=0 && part===''+intKey) {\n prevCurr[prevPart] = []\n } else {\n prevCurr[prevPart] = {}\n }\n curr = prevCurr[prevPart]\n }\n }\n if (prev && prevPart && prev[prevPart]!==value) {\n if (value && typeof value=='object') {\n curr = prev[prevPart]\n if (!curr) {\n // last part of path in html does not exist yet, create it\n prev[prevPart] = {}\n curr = prev[prevPart]\n }\n for (const prop in value) {\n if (curr[prop]!==value[prop]) {\n curr[prop] = value[prop]\n }\n }\n } else {\n prev[prevPart] = value\n }\n }\n })\n}\n\n/**\n * Renders an array value by applying templates for each entry\n * Replaces or removes existing DOM children if needed\n * Reuses (doesn't touch) DOM children if template doesn't change\n * FIXME: this doesn't handle situations where there is no matching template\n * this messes up self healing. check renderObjectByTemplates for a better implementation\n */\nexport function arrayByTemplates(context)\n{\n const attribute = this.options.attribute\n\n let items = context.element.querySelectorAll(':scope > ['+attribute+'-key]')\n // do single merge strategy for now, in future calculate optimal merge strategy from a number\n // now just do a delete if a key <= last key, insert if a key >= last key\n let lastKey = 0\n let skipped = 0\n context.list = context.value\n for (let item of items) {\n let currentKey = parseInt(item.getAttribute(attribute+'-key'))\n if (currentKey>lastKey) {\n // insert before\n context.index = lastKey\n context.element.insertBefore(this.applyTemplate(context), item)\n } else if (currentKey<lastKey) {\n // remove this\n item.remove()\n } else {\n // check that all data-bind params start with current json path or ':root', otherwise replaceChild\n let bindings = Array.from(item.querySelectorAll(`[${attribute}]`))\n if (item.matches(`[${attribute}]`)) {\n bindings.unshift(item)\n }\n let needsReplacement = bindings.find(b => {\n let databind = b.getAttribute(attribute)\n return (databind.substr(0,5)!==':root' \n && databind.substr(0, context.path.length)!==context.path)\n })\n if (!needsReplacement) {\n if (item[Symbol.bindTemplate]) {\n let newTemplate = this.findTemplate(context.templates, context.list[lastKey])\n if (newTemplate != item[Symbol.bindTemplate]){\n needsReplacement = true\n if (!newTemplate) {\n skipped++\n }\n }\n }\n }\n if (needsReplacement) {\n context.index = lastKey\n context.element.replaceChild(this.applyTemplate(context), item)\n }\n }\n lastKey++\n if (lastKey>=context.value.length) {\n break\n }\n }\n items = context.element.querySelectorAll(':scope > ['+attribute+'-key]')\n let length = items.length + skipped\n if (length > context.value.length) {\n while (length > context.value.length) {\n let child = context.element.querySelectorAll(':scope > :not(template)')?.[length-1]\n child?.remove()\n length--\n }\n } else if (length < context.value.length ) {\n while (length < context.value.length) {\n context.index = length\n context.element.appendChild(this.applyTemplate(context))\n length++\n }\n }\n if (this.options.twoway) {\n trackDomList.call(this, context.element)\n }\n}\n\n/**\n * Renders an object value by applying templates for each entry (Object.entries)\n * Replaces,moves or removes existing DOM children if needed\n * Reuses (doesn't touch) DOM children if template doesn't change\n */\nexport function objectByTemplates(context)\n{\n const attribute = this.options.attribute\n context.list = context.value\n\n let items = Array.from(context.element.querySelectorAll(':scope > ['+attribute+'-key]'))\n for (let key in context.list) {\n context.index = key\n let item = items.shift()\n if (!item) { // more properties than rendered items\n let clone = this.applyTemplate(context)\n context.element.appendChild(clone)\n continue\n }\n if (item.getAttribute(attribute+'-key')!=key) { \n // next item doesn't match key\n items.unshift(item) // put item back for next cycle\n let outOfOrderItem = context.element.querySelector(':scope > ['+attribute+'-key=\"'+key+'\"]') //FIXME: escape key\n if (!outOfOrderItem) {\n let clone = this.applyTemplate(context)\n context.element.insertBefore(clone, item)\n continue // new template doesn't need replacement, so continue \n } else {\n context.element.insertBefore(outOfOrderItem, item)\n item = outOfOrderItem // check needsreplacement next\n items = items.filter(i => i!=outOfOrderItem)\n }\n }\n let newTemplate = this.findTemplate(context.templates, context.list[context.index])\n if (newTemplate != item[Symbol.bindTemplate]){\n let clone = this.applyTemplate(context)\n context.element.replaceChild(clone, item)\n }\n }\n // clean up remaining items\n while (items.length) {\n let item = items.shift()\n item.remove()\n }\n}\n\n/**\n * renders the contents of an html element by rendering\n * a matching template, once.\n */\nexport function fieldByTemplates(context)\n{\n const rendered = context.element.querySelector(':scope > :not(template)')\n const template = this.findTemplate(context.templates, context.value)\n context.parent = getParentPath(context.element)\n if (rendered) {\n if (template) {\n if (rendered?.[Symbol.bindTemplate] != template) {\n const clone = this.applyTemplate(context)\n context.element.replaceChild(clone, rendered)\n }\n } else {\n context.element.removeChild(rendered)\n }\n } else if (template) {\n const clone = this.applyTemplate(context)\n context.element.appendChild(clone)\n }\n}\n\nfunction getParentPath(el, attribute)\n{\n const parentEl = el.parentElement?.closest(`[${attribute}-list],[${attribute}-map]`)\n if (!parentEl) {\n return ''\n }\n if (parentEl.hasAttribute(`${attribute}-list`)) {\n return parentEl.getAttribute(`${attribute}-list`)+'.'\n }\n return parentEl.getAttribute(`${attribute}-map`)+'.'\n}\n\n/**\n * renders a single input type\n * for radio/checkbox inputs it only sets the checked attribute to true/false\n * if the value attribute matches the current value\n * for other inputs the value attribute is updated\n */\nexport function input(context)\n{\n const el = context.element\n let value = context.value\n\n element.call(this, context)\n if (typeof value == 'undefined') {\n value = ''\n }\n if (el.type=='checkbox' || el.type=='radio') {\n if (matchValue(el.value, value)) {\n el.checked = true\n } else {\n el.checked = false\n }\n } else if (!matchValue(el.value, value)) {\n el.value = ''+value\n }\n}\n\n/**\n * Sets the value of the button, doesn't touch the innerHTML\n */\nexport function button(context)\n{\n element.call(this, context, 'value')\n}\n\n/**\n * Sets the selected attribute of select options\n */\nexport function select(context)\n{\n const el = context.element\n let value = context.value\n\n if (value === null) {\n value = ''\n }\n if (typeof value!='object') {\n if (el.multiple) {\n if (Array.isArray(value)) { //FIXME: cannot be true, since typeof != 'object'\n for (let option of el.options) {\n if (value.indexOf(option.value)===false) {\n option.selected = false\n } else {\n option.selected = true\n }\n }\n }\n } else {\n let option = el.options.find(o => matchValue(o.value,value))\n if (option) {\n option.selected = true\n option.setAttribute('selected', true)\n }\n }\n } else { // value is a non-null object\n if (value.options) {\n setSelectOptions(el, value.options)\n }\n if (value.selected) {\n select(Object.asssign({}, context, {value:value.selected}))\n }\n setProperties(el, value, 'name', 'id', 'selectedIndex', 'className') // allow innerHTML? if so call element instead\n }\n}\n\n/**\n * adds a single option to a select element. The option.text property is optional, if not set option.value is used.\n * @param select The select element\n * @param option An option descriptor, either a string, object with {text,value,defaultSelected,selected} properties or an Option object\n */\nexport function addOption(select, option)\n{\n if (!option) {\n return\n }\n if (typeof option !== 'object') {\n select.options.add(new Option(''+option))\n } else if (option.text) {\n select.options.add(new Option(option.text, option.value, option.defaultSelected, option.selected))\n } else if (typeof option.value != 'undefined') {\n select.options.add(new Option(''+option.value, option.value, option.defaultSelected, option.selected))\n }\n}\n\n/**\n * This function clears all existing options of a select element, and adds the specified options.\n */\nexport function setSelectOptions(select,options)\n{\n //@TODO: only update in case of changes?\n select.innerHTML = ''\n if (Array.isArray(options)) {\n for (const option of options) {\n addOption(select, option)\n }\n } else if (options && typeof options == 'object') {\n for (const option in options) {\n addOption(select, { text: options[option], value: option })\n }\n }\n}\n\n/**\n * Sets the innerHTML and href, id, title, target, name, newwindow, nofollow attributes of an anchor\n */\nexport function anchor(context)\n{\n element.call(this, context, 'target', 'href', 'name', 'newwindow', 'nofollow')\n if (this.options.twoway) {\n batch(() => {\n updateProperties.call(this, context, ['target', 'href', 'name', 'newwindow', 'nofollow'])\n })\n }\n}\n\n/**\n * Sets the title, id, alt and src attributes of an image.\n */\nexport function image(context)\n{\n setProperties(context.element, context.value, 'title', 'alt', 'src', 'id')\n if (this.options.twoway) {\n batch(() => {\n updateProperties.call(this, context, ['title', 'alt', 'src', 'id'])\n })\n }\n}\n\n/**\n * Sets the title, id and src attribute of an iframe\n */\nexport function iframe(context)\n{\n setProperties(context.element, context.value, 'title', 'src', 'id')\n if (this.options.twoway) {\n batch(() => {\n updateProperties.call(this, context, ['title','src','id'])\n })\n }\n}\n\n/**\n * Sets the content and id attribute of a meta element\n */\nexport function meta(context)\n{\n setProperties(context.element, context.value, 'content', 'id')\n if (this.options.twoway) {\n batch(() => {\n updateProperties.call(this, context, ['content','id'])\n })\n }\n}\n\n/**\n * sets the innerHTML and title and id properties of any HTML element\n */\nexport function element(context, ...extraprops)\n{\n const el = context.element\n let value = context.value\n let valueIsString = false\n if (typeof value!='undefined' && value!==null) {\n let strValue = ''+value\n if (typeof value!='object' || strValue.substring(0,8)!='[object ') {\n value = { innerHTML: value }\n valueIsString = true\n }\n }\n const props = ['innerHTML','title','id','className'].concat(extraprops)\n setProperties(el, value, ...props)\n if (this.options.twoway) {\n trackDomField.call(this, context.element, props, valueIsString)\n }\n}\n\n/**\n * Sets a list of properties on a dom element, equal to \n * the string value of a data object\n * only updates the dom element if the property doesn't match\n */\nexport function setProperties(el, data, ...properties) {\n if (!data || typeof data!=='object') {\n return\n }\n for (const property of properties) {\n if (typeof data[property] === 'undefined') {\n continue\n }\n if (matchValue(el[property], data[property])) {\n continue\n }\n if (data[property] === null) {\n el[property] = ''\n } else {\n el[property] = ''+data[property]\n }\n }\n}\n\nexport function getProperties(el, ...properties) {\n const result = {}\n for (const property of properties) {\n switch(property) {\n default: \n result[property] = el[property]\n break\n }\n }\n return result\n}\n\n/**\n * Returns true if a matches b, either by having the\n * same string value, or matching string :empty against a falsy value\n */\nexport function matchValue(a,b)\n{\n if (a==':empty' && !b) {\n return true\n }\n if (b==':empty' && !a) {\n return true\n }\n if (''+a == ''+b) {\n return true\n }\n return false\n}\n", "import { throttledEffect, destroy } from './state.mjs'\nimport { escape_html, fixed_content } from './bind.transformers.mjs'\nimport * as render from './bind.render.mjs'\n\nif (!Symbol.bindTemplate) {\n Symbol.bindTemplate = Symbol('bindTemplate')\n}\n\n/**\n * Implements one way databinding, updating dom elements with matching attributes\n * to changes in signals (see state.mjs)\n * \n * @class\n */\nclass SimplyBind\n{\n \n /**\n * @param Object options - a set of options for this instance, options may include:\n * - root (signal) (required) - the root data object that contains al signals that can be bound\n * - container (HTMLElement) - the dom element to use as the root for all bindings\n * - attribute (string) - the prefix for the field, list and map attributes, e.g. 'data-bind'\n * - transformers (object name:function) - a map of transformer names and functions\n * - render (object with field, list and map properties)\n */\n constructor(options)\n {\n /**\n * A map of HTMLElements and the data bindings on each, in the form of \n * the connectedSignal returned by the (throttled)Effect.\n * @type {Map}\n * @public\n */\n this.bindings = new Map()\n\n const defaultTransformers = {\n escape_html,\n fixed_content\n }\n const defaultOptions = {\n container: document.body,\n attribute: 'data-flow',\n transformers: defaultTransformers,\n render: {\n field: [render.field],\n list: [render.list],\n map: [render.map]\n },\n renderers: {\n 'INPUT':render.input,\n 'BUTTON':render.button,\n 'SELECT':render.select,\n 'A':render.anchor,\n 'IMG':render.image,\n 'IFRAME':render.iframe,\n 'META':render.meta,\n 'TEMPLATE':null,\n '*':render.element\n },\n twoway: false\n }\n if (!options?.root) {\n throw new Error('bind needs at least options.root set')\n }\n this.options = Object.assign({}, defaultOptions, options)\n if (options.transformers) {\n this.options.transformers = Object.assign({}, defaultTransformers, options?.transformers)\n }\n const attribute = this.options.attribute\n const bindAttributes = [attribute+'-field',attribute+'-list',attribute+'-map']\n const transformAttribute = attribute+'-transform'\n\n const getBindingAttribute = (el) => {\n const foundAttribute = bindAttributes.find(attr => el.hasAttribute(attr))\n if (!foundAttribute) {\n console.error('No matching attribute found',el,bindAttributes)\n }\n return foundAttribute\n }\n\n // sets up the effect that updates the element if its\n // data binding value changes\n const renderElement = (el) => {\n this.bindings.set(el, throttledEffect(() => {\n if (!el.isConnected) {\n // el is no longer part of this document\n untrack(el, this.getBindingPath(el))\n destroy(this.bindings.get(el))\n // doing this here instead of in a mutationobserver\n // allows an element to be temporary removed and then inserted\n // without the binding having to be reset\n return\n }\n let context = {\n templates: el.querySelectorAll(':scope > template'),\n attribute: getBindingAttribute(el)\n }\n context.path = this.getBindingPath(el)\n context.value = getValueByPath(this.options.root, context.path)\n context.element = el\n track(el, context)\n runTransformers(context)\n }, 50))\n }\n\n // finds and runs applicable transformers\n // creates a stack of transformers, calls the topmost\n // each transformer can opt to call the next or not\n // transformers should return the context object (possibly altered)\n const runTransformers = (context) => {\n let transformers\n switch(context.attribute) {\n case this.options.attribute+'-field':\n transformers = Array.from(this.options.render.field)\n break\n case this.options.attribute+'-list':\n transformers = Array.from(this.options.render.list)\n break\n case this.options.attribute+'-map':\n transformers = Array.from(this.options.render.map)\n break\n default:\n throw new Error('no valid context attribute specified',context)\n break\n }\n if (context.element.hasAttribute(transformAttribute)) {\n context.element.getAttribute(transformAttribute)\n .split(' ').filter(Boolean)\n .forEach(t => {\n if (this.options.transformers[t]) {\n transformers.push(this.options.transformers[t])\n } else {\n console.warn('No transformer with name '+t+' configured', {cause:context.element})\n }\n })\n }\n let next\n for (let transformer of transformers) {\n next = ((next, transformer) => {\n return (context) => {\n return transformer.call(this, context, next)\n }\n })(next, transformer)\n }\n next(context)\n }\n\n // given a set of elements with data bind attribute\n // this renders each of those elements\n const applyBindings = (bindings) => {\n for (let bindingEl of bindings) {\n if (!this.bindings.get(bindingEl)) { // bindingEl may have moved from somewhere else in this document\n renderElement(bindingEl)\n }\n }\n }\n\n // this handles the mutation observer changes\n // if any element is added, and has a data bind attribute\n // it applies that data binding\n const updateBindings = (changes) => {\n const selector = `[${attribute}-field],[${attribute}-list],[${attribute}-map]`\n for (const change of changes) {\n if (change.type==\"childList\" && change.addedNodes) {\n for (let node of change.addedNodes) {\n if (node instanceof HTMLElement) {\n let bindings = Array.from(node.querySelectorAll(selector))\n if (node.matches(selector)) {\n bindings.unshift(node)\n }\n if (bindings.length) {\n applyBindings(bindings)\n }\n }\n }\n }\n }\n }\n\n // this responds to elements getting added to the dom\n // and if any have data bind attributes, it applies those bindings\n this.observer = new MutationObserver((changes) => {\n updateBindings(changes)\n })\n\n this.observer.observe(this.options.container, {\n subtree: true,\n childList: true\n })\n\n // this finds elements with data binding attributes and applies those bindings\n // must come after setting up the observer, or included templates\n // won't trigger their own bindings\n const bindings = this.options.container.querySelectorAll(\n ':is(['+this.options.attribute+'-field]'+\n ',['+this.options.attribute+'-list]'+\n ',['+this.options.attribute+'-map]):not(template)'\n )\n if (bindings.length) {\n applyBindings(bindings)\n }\n\n }\n\n /**\n * Finds the first matching template and creates a new DocumentFragment\n * with the correct data bind attributes in it (prepends the current path)\n * @param Context context\n * @return DocumentFragment\n */\n applyTemplate(context)\n {\n const path = context.path\n const parent = context.parent\n const templates = context.templates\n const list = context.list\n const index = context.index\n const value = list ? list[index] : context.value\n\n let template = this.findTemplate(templates, value)\n if (!template) {\n let result = new DocumentFragment()\n result.innerHTML = '<!-- no matching template -->'\n return result\n }\n let clone = template.content.cloneNode(true)\n if (!clone.children?.length) {\n return clone\n }\n if (clone.children.length>1) {\n throw new Error('template must contain a single root node', { cause: template })\n }\n const attribute = this.options.attribute\n\n const attributes = [attribute+'-field',attribute+'-list',attribute+'-map']\n const bindings = clone.querySelectorAll(`[${attribute}-field],[${attribute}-list],[${attribute}-map]`)\n for (let binding of bindings) {\n if (binding.tagName=='TEMPLATE') {\n continue\n }\n const attr = attributes.find(attr => binding.hasAttribute(attr))\n let bind = binding.getAttribute(attr)\n bind = this.applyLinks(template.links, bind)\n if (bind.substring(0, ':root.'.length)==':root.') {\n binding.setAttribute(attr, bind.substring(':root.'.length))\n } else if (bind==':value' && index!=null) {\n binding.setAttribute(attr, path+'.'+index)\n } else if (index!=null) {\n binding.setAttribute(attr, path+'.'+index+'.'+bind)\n } else {\n binding.setAttribute(attr, parent+bind)\n }\n }\n if (typeof index !== 'undefined') {\n clone.children[0].setAttribute(attribute+'-key',index)\n }\n // keep track of the used template, so if that changes, the item can be updated\n clone.children[0][Symbol.bindTemplate] = template\n\n // return clone, not the firstChild, so that all whitespace is cloned as well\n return clone\n }\n\n parseLinks(links)\n {\n let result = {}\n links = links.split(';').map(link => link.trim())\n for (let link of links) {\n link = link.split('=')\n result[link[0].trim()] = link[1].trim()\n }\n return result\n }\n\n applyLinks(links, value)\n {\n for (let link in links) {\n if (value.startsWith(link+'.')) {\n return links[link] + value.substr(link.length)\n } else if (value==link) {\n return links[link]\n }\n }\n return value\n }\n\n /**\n * Returns the path referenced in either the field, list or map attribute\n * @param HTMLElement el\n * @return string The path referenced, or void\n */\n getBindingPath(el)\n {\n const attributes = [\n this.options.attribute+'-field', \n this.options.attribute+'-list',\n this.options.attribute+'-map'\n ]\n for (let attr of attributes) {\n if (el.hasAttribute(attr)) {\n return el.getAttribute(attr)\n }\n }\n }\n\n /**\n * Finds the first template from an array of templates that\n * matches the given value. \n */\n findTemplate(templates, value)\n {\n const templateMatches = t => {\n // find the value to match against (e.g. data-bind=\"foo\")\n let path = this.getBindingPath(t)\n let currentItem\n if (path) {\n if (path.substr(0,6)==':root.') {\n currentItem = getValueByPath(this.options.root, path)\n } else {\n currentItem = getValueByPath(value, path)\n }\n } else {\n currentItem = value\n }\n\n // then check the value against pattern, if set (e.g. data-bind-match=\"bar\")\n const strItem = ''+currentItem\n let matches = t.getAttribute(this.options.attribute+'-match')\n if (matches) {\n if (matches===':empty' && !currentItem) {\n return t\n } else if (matches===':notempty' && currentItem) {\n return t\n }\n if (strItem == matches) {\n return t\n }\n }\n if (!matches) {\n // no data-bind-match is set, so return this template\n return t\n }\n }\n let template = Array.from(templates).find(templateMatches)\n let links = null\n if (template?.hasAttribute(this.options.attribute+'-link')) {\n links = this.parseLinks(template.getAttribute(this.options.attribute+'-link'))\n }\n let rel = template?.getAttribute('rel')\n if (rel) {\n let replacement = document.querySelector('template#'+rel)\n if (!replacement) {\n throw new Error('Could not find template with id '+rel)\n }\n template = replacement\n }\n if (template) {\n template.links = links\n }\n return template\n }\n\n destroy()\n {\n this.bindings.forEach(binding => {\n destroy(binding)\n })\n this.bindings = new Map()\n this.observer.disconnect()\n }\n\n}\n\n/**\n * Returns a new instance of SimplyBind. This is the normal start\n * of a data bind flow\n */\nexport function bind(options)\n{\n return new SimplyBind(options)\n}\n\nconst tracking = new Map()\n\nexport function trace(path)\n{\n return tracking.get(path)\n}\n\nfunction track(el, context) {\n if (!tracking.has(context.path)) {\n tracking.set(context.path, [context])\n } else {\n tracking.get(context.path).push(context)\n }\n}\n\nfunction untrack(el, path) {\n let list = tracking.get(path)\n if (list) {\n list = list.filter(context => context.element == el)\n tracking.set(path, list)\n }\n}\n\n\n/**\n * Returns the value by walking the given path as a json pointer, starting at root\n * if you have a property with a '.' in its name urlencode the '.', e.g: %46\n * \n * @param HTMLElement root\n * @param string path e.g. 'foo.bar'\n * @return mixed the value found by walking the path from the root object or undefined\n */\nexport function getValueByPath(root, path)\n{\n let parts = path.split('.')\n let curr = root\n let part\n part = parts.shift()\n let prevPart = null\n while (part && curr) {\n part = decodeURIComponent(part)\n if (part=='0' && !Array.isArray(curr)) {\n // ignore so that data-flow-list=\"nonarray\" will work\n } else if (part==':key') {\n curr = prevPart\n } else if (part==':value') {\n // do nothing\n } else if (Array.isArray(curr) && typeof curr[part]=='undefined' && curr[0]) {\n curr = curr[0][part] // so that data-flow-field=\"array.foo\" works\n } else {\n curr = curr[part]\n }\n prevPart = part\n part = parts.shift()\n }\n return curr\n}\n", "import {signal, effect, throttledEffect, batch} from './state.mjs'\n\n/**\n * This class implements a pluggable data model, where you can\n * add effects that are run only when either an option for that\n * effect changes, or when an effect earlier in the chain of\n * effects changes.\n */\nclass SimplyFlowModel {\n\n\t/**\n\t * Creates a new datamodel, with a state property that contains\n\t * all the data passed to this constructor\n\t * @param state\tObject with all the data for this model\n\t * @throws Error if state is not set\n\t */\n\tconstructor(state) {\n\t\tif (!state) {\n\t\t\tthrow new Error('no options set')\n\t\t}\n\t\tif (state.data==null || typeof state.data[Symbol.iterator] !== 'function') {\n\t\t\tconsole.warn('SimplyFlowModel: options.data is not iterable')\n\t\t}\n\t\tthis.state = signal(state)\n\t\tif (!this.state.options) {\n\t\t\tthis.state.options = {}\n\t\t}\n\t\tthis.effects = [{current:this.state.data}]\n\t\tthis.view = {\n current: this.state.data\n }\n\t}\n\n\t/**\n\t * Adds an effect to run whenever a signal it depends on\n\t * changes. this.state is the usual signal.\n\t * The `fn` function param is not itself an effect, but must return\n\t * and effect function. `fn` takes one param, which is the data signal.\n\t * This signal will always have at least a `current` property.\n\t * The result of the effect function is pushed on to the this.effects\n\t * list. And the last effect added is set as this.view\n\t */\n\taddEffect(fn) {\n\t\tif (!fn || typeof fn !=='function') {\n\t\t\tthrow new Error('addEffect requires an effect function as its parameter', { cause: fn })\n\t\t}\n\t\tconst dataSignal = this.effects[this.effects.length-1]\n\t\tconst connectedSignal = fn.call(this, dataSignal)\n\t\tif (!connectedSignal || !connectedSignal[Symbol.Signal]) {\n\t\t\tthrow new Error('addEffect function parameter must return a Signal', { cause: fn })\n\t\t}\n\t\tthis.view = connectedSignal\n\t\tthis.effects.push(this.view)\n\t}\n}\n\nexport function model(options) {\n\treturn new SimplyFlowModel(options)\n}\n\n/**\n * Returns a function for model.addEffect that sorts the input data\n * \n * Options:\n * - direction (string) default 'asc' - change to 'desc' to sort in descending order\n * - sortBy (string) (optional) - used by the default sorting function to select the property to sort on\n * - sortFn (function) (required - set by default) - the sort function to use\n */\nexport function sort(options={}) {\n\treturn function(data) {\n\t\t// initialize the sort options, only gets called once\n\t\tthis.state.options.sort = Object.assign({\n\t\t\tdirection: 'asc',\n\t\t\tsortBy: null,\n\t\t\tsortFn: ((a,b) => {\n\t\t\t\tconst sort = this.state.options.sort\n\t\t\t\tconst sortBy = sort.sortBy\n\t\t\t\tif (!sort.sortBy) {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t\tconst larger = sort.direction == 'asc' ? 1 : -1\n\t\t\t\tconst smaller = sort.direction == 'asc' ? -1 : 1\n\t\t\t\tif (typeof a?.[sortBy] === 'undefined') {\n\t\t\t\t\tif (typeof b?.[sortBy] === 'undefined') {\n\t\t\t\t\t\treturn 0\n\t\t\t\t\t}\n\t\t\t\t\treturn larger\n\t\t\t\t}\n\t\t\t\tif (typeof b?.[sortBy] === 'undefined') {\n\t\t\t\t\treturn smaller\n\t\t\t\t}\n\t\t\t\tif (a[sortBy]<b[sortBy]) {\n\t\t\t\t\treturn smaller\n\t\t\t\t} else if (a[sortBy]>b[sortBy]) {\n\t\t\t\t\treturn larger\n\t\t\t\t} else {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t})\n\t\t}, options);\n\t\t// then return the effect, which is called when\n\t\t// either the data or the sort options change\n\t\treturn throttledEffect(() => {\n\t\t\tconst sort = this.state.options.sort\n\t\t\tif (sort?.sortBy && sort?.direction) {\n\t\t\t\treturn data.current.toSorted(sort?.sortFn)\n\t\t\t}\n\t\t\treturn data.current\n\t\t}, 50)\n\t}\n}\n\n/**\n * Returns a function for model.addEffect that implements paging\n * for the input data. It will return a slice of the data matching\n * the page and pageSize options.\n * \n * Options:\n * - page (int) default 1 - which page to show, starts at 1\n * - pageSize (int) default 20 - how many items in a single page\n * - max (int) (calculated) - how many pages in total\n */\nexport function paging(options={}) {\n\treturn function(data) {\n\t\t// initialize the paging options\n\t\tthis.state.options.paging = Object.assign({\n\t\t\tpage: 1,\n\t\t\tpageSize: 20,\n\t\t\tmax: 1\n\t\t}, options)\n\t\treturn throttledEffect(() => {\n\t\t\treturn batch(() => {\n\t\t\t\tconst paging = this.state.options.paging\n\t\t\t\tif (!paging.pageSize) {\n\t\t\t\t\tpaging.pageSize = 20\n\t\t\t\t}\n\t\t\t\tpaging.max = Math.ceil(this.state.data.length / paging.pageSize)\n\t\t\t\tpaging.page = Math.max(1, Math.min(paging.max, paging.page))\n\n\t\t\t\tconst start = (paging.page-1) * paging.pageSize\n\t\t\t\tconst end = start + paging.pageSize\n\t\t\t\treturn data.current.slice(start, end)\n\t\t\t})\n\t\t}, 50)\n\t}\n}\n\n/**\n * Returns a function for model.addEffect that filters rows from the data,\n * using a custom filter function `options.matches`\n * \n * Options:\n * - name (string) (required) - the name of this filter, must be unique\n * - matches (function) (required) - the filter function to apply to the data\n * - enabled (bool) (required) - filter is applied only when enabled is set to true\n */\nexport function filter(options) {\n\tif (!options?.name || typeof options.name!=='string') {\n\t\tthrow new Error('filter requires options.name to be a string')\n\t}\n\tif (!options.matches || typeof options.matches!=='function') {\n\t\tthrow new Error('filter requires options.matches to be a function')\n\t}\n\treturn function(data) {\n\t\tif (this.state.options[options.name]) {\n\t\t\tthrow new Error('a filter with this name already exists on this model')\n\t\t}\n\t\tthis.state.options[options.name] = options\n\t\treturn throttledEffect(() => {\n\t\t\tif (this.state.options[options.name].enabled) {\n\t\t\t\treturn data.current.filter(this.state.options[options.name].matches.bind(this))\n\t\t\t}\n\t\t\treturn data.current\n\t\t}, 50)\n\t}\n}\n\n/**\n * Returns a function for model.addEffect that filters the data to only contain\n * columns (properties) that aren't hidden. Automatically runs again if any columns\n * hidden property changes.\n * \n * Options:\n * - columns (object) (required) - an object with properties describing each column. Each \n * property must be an object with an optional `hidden` property. If set to a truthy value,\n * and property in the dataset with the same name, will be filtered out.\n */\nexport function columns(options={}) {\n\tif (!options\n\t\t|| typeof options!=='object'\n\t\t|| Object.keys(options).length===0) {\n\t\tthrow new Error('columns requires options to be an object with at least one property')\n\t}\n\treturn function(data) {\n\t\tthis.state.options.columns = options\n\t\treturn throttledEffect(() => {\n\t\t\treturn data.current.map(input => {\n\t\t\t\tlet result = {}\n\t\t\t\tfor (let key of Object.keys(this.state.options.columns)) {\n\t\t\t\t\tif (!this.state.options.columns[key]?.hidden) {\n\t\t\t\t\t\tresult[key] = input[key] ?? null\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t})\n\t\t}, 50)\n\t}\n}\n\n/**\n * Returns a function for use with model.addEffect, with the given options set\n * as model.options.scroll. The effect will return a slice of the input data, which\n * makes it easy to render just a part (slice) of the whole data.\n * \n * Options are:\n * - offset (int) default 0 (optional) - the offset in the data to start the slice\n * - rowCount (int) default 20 (optional / calculated) - the number of rows in the slice\n * - rowHeight (int) default 26 (optional) - the height of a single row in pixels\n * - itemsPerRow (int) default 1 (optional) - the number of items on a single row\n * - size (int) default data.current.length (calculated) - how many rows inside data.current before slicing\n * - scrollbar (HTMLElement) defualt null (optional) - if set, an effect is added to update this elements \n * \t height if data.current.length changes\n * - container (HTMLElement) default null (optional) - if set, a scroll listener is added to this element, \n * which will update the options.offset signal and trigger the slice effect. It will also set the rowCount.\n */\nexport function scroll(options) {\n\n\treturn function(data) {\n\t\tthis.state.options.scroll = Object.assign({\n\t\t\toffset: 0,\n\t\t\trowHeight: 26,\n\t\t\trowCount: 20,\n\t\t\titemsPerRow: 1,\n\t\t\tsize: data.current.length\n\t\t}, options)\n\t\tconst scrollOptions = this.state.options.scroll\n\n\t\tconst scrollbar = scrollOptions.scrollbar \n\t\t\t|| scrollOptions.container?.querySelector('[data-flow-scrollbar]')\n\t\tif (scrollbar) {\n\t\t\tif (scrollOptions.container) {\n\t\t\t\tscrollOptions.container.addEventListener('scroll', (evt) => {\n\t\t\t\t\tscrollOptions.offset = Math.floor(scrollOptions.container.scrollTop\n\t\t\t\t\t\t/ (scrollOptions.rowHeight*scrollOptions.itemsPerRow)\n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tthrottledEffect(() => {\n\t\t\t\tscrollOptions.size = data.current.length * scrollOptions.rowHeight\n\t\t\t\tscrollbar.style.height = scrollOptions.size + 'px'\n\t\t\t}, 50)\n\t\t}\n\n\t\treturn throttledEffect(() => {\n\t\t\tif (scrollOptions.container) {\n\t\t\t\t//TODO: add a resize listener so that if the size of the container\n\t\t\t\t// changes, the rowCount is calculated again\n\t\t\t\tscrollOptions.rowCount = Math.ceil(\n\t\t\t\t\tscrollOptions.container.getBoundingClientRect().height \n\t\t\t\t\t/ scrollOptions.rowHeight\n\t\t\t\t)\n\t\t\t}\n\t\t\tscrollOptions.data = data.current\n\t\t\tlet start = Math.min(scrollOptions.offset, data.current.length-1)\n\t\t\tlet end = start + scrollOptions.rowCount\n\t\t\tif (end > data.current.length) {\n\t\t\t\tend = data.current.length\n\t\t\t\tstart = end - scrollOptions.rowCount\n\t\t\t}\n\t\t\treturn data.current.slice(start, end)\n\t\t}, 50)\n\t}\n}", "export class SimplyRender extends HTMLElement \n{\n constructor()\n {\n super()\n }\n\n connectedCallback()\n {\n let templateId = this.getAttribute(\"rel\")\n let template = document.getElementById(templateId)\n\n if (template) {\n let content = template.content.cloneNode(true)\n for (const node of content.childNodes) {\n const clone = node.cloneNode(true)\n if (clone.nodeType == document.ELEMENT_NODE) {\n clone.querySelectorAll(\"template\").forEach(function(t) {\n t.setAttribute(\"simply-render\", \"\") //FIXME: whats this?\n })\n if (this.attributes) {\n for (const attr of this.attributes) {\n if (attr.name!='rel') {\n clone.setAttribute(attr.name, attr.value)\n }\n }\n }\n }\n this.parentNode.insertBefore(clone, this)\n }\n this.parentNode.removeChild(this)\n } else {\n const observe = () => {\n const observer = new MutationObserver(() => {\n template = document.getElementById(templateId)\n if (template) {\n observer.disconnect()\n this.replaceWith(this) // trigger connectedCallback?\n }\n })\n observer.observe(globalThis.document, {\n subtree: true,\n childList: true,\n })\n }\n\n observe()\n }\n }\n}\n\nif (!customElements.get('simply-render')) {\n customElements.define('simply-render', SimplyRender);\n}", "import { bind } from './bind.mjs'\nimport * as model from './model.mjs'\nimport * as state from './state.mjs'\nimport './render.mjs'\nimport * as dom from './dom.mjs'\n\nif (!globalThis.simply) {\n\tglobalThis.simply = {}\n}\nObject.assign(globalThis.simply, {\n\tbind,\n\tflow: model,\n\tstate,\n\tdom\n})\n\nexport default globalThis.simply"],
5
+ "mappings": "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",
6
+ "names": ["state_exports", "__export", "addTracer", "batch", "clockEffect", "clone", "destroy", "effect", "makeContext", "notifyGet", "notifySet", "signal", "signals", "throttledEffect", "trace", "untracked", "signalHandler", "target", "property", "receiver", "value", "args", "l", "result", "current", "descriptor", "v", "tracers", "tracing", "prop", "getListeners", "listener", "tracer", "callTracers", "getset", "params", "batchedListeners", "batchMode", "self", "context", "listeners", "change", "propListeners", "addContext", "currentEffect", "computeStack", "clearContext", "currentCompute", "setListeners", "listenersMap", "computeMap", "compute", "connectedSignals", "clearListeners", "s", "effectStack", "effectMap", "signalStack", "fn", "f", "connectedSignal", "computeEffect", "runBatchedListeners", "copyBatchedListeners", "throttleTime", "throttled", "hasChange", "clock", "lastTick", "hasChanged", "pos", "remember", "deep", "seen", "innerClone", "key", "escape_html", "context", "next", "content", "fixed_content", "dom_exports", "__export", "signal", "trackDomField", "trackDomList", "domSignals", "domSignalHandler", "target", "property", "receiver", "value", "notifyGet", "signal", "signals", "el", "options", "domListen", "observers", "oldContentHTML", "oldContentText", "observer", "mutationList", "changes", "mutation", "prop", "notifySet", "makeContext", "prevValue", "evt", "trackDomList", "element", "path", "s", "throttledEffect", "children", "untracked", "batch", "key", "currentList", "getValueByPath", "source", "item", "setValueByPath", "trackDomField", "props", "valueIsString", "updateValue", "getProperties", "field", "context", "fieldByTemplates", "renderer", "list", "length", "arrayByTemplates", "map", "objectByTemplates", "isInt", "s", "setValueByPath", "root", "path", "value", "batch", "parts", "curr", "part", "prev", "prevPart", "prevCurr", "intKey", "prop", "attribute", "items", "lastKey", "skipped", "item", "currentKey", "bindings", "needsReplacement", "b", "databind", "newTemplate", "trackDomList", "key", "clone", "outOfOrderItem", "i", "rendered", "template", "getParentPath", "el", "parentEl", "input", "element", "matchValue", "button", "select", "option", "o", "setSelectOptions", "setProperties", "addOption", "options", "anchor", "image", "iframe", "meta", "extraprops", "valueIsString", "strValue", "props", "trackDomField", "data", "properties", "property", "getProperties", "result", "a", "SimplyBind", "options", "defaultTransformers", "escape_html", "fixed_content", "defaultOptions", "field", "list", "map", "input", "button", "select", "anchor", "image", "iframe", "meta", "element", "attribute", "bindAttributes", "transformAttribute", "getBindingAttribute", "el", "foundAttribute", "attr", "renderElement", "throttledEffect", "untrack", "destroy", "context", "getValueByPath", "track", "runTransformers", "transformers", "t", "next", "transformer", "applyBindings", "bindings", "bindingEl", "updateBindings", "changes", "selector", "change", "node", "path", "parent", "templates", "index", "value", "template", "result", "clone", "attributes", "binding", "bind", "links", "link", "templateMatches", "currentItem", "strItem", "matches", "rel", "replacement", "tracking", "track", "el", "context", "tracking", "untrack", "path", "list", "getValueByPath", "root", "parts", "curr", "part", "prevPart", "model_exports", "__export", "columns", "filter", "model", "paging", "scroll", "sort", "SimplyFlowModel", "state", "signal", "fn", "dataSignal", "connectedSignal", "model", "options", "sort", "data", "a", "b", "sortBy", "larger", "smaller", "throttledEffect", "paging", "batch", "start", "end", "filter", "columns", "input", "result", "key", "scroll", "scrollOptions", "scrollbar", "evt", "SimplyRender", "templateId", "template", "content", "node", "clone", "t", "attr", "observer", "bind", "model_exports", "state_exports", "dom_exports", "flow_default"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simplyflow",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
4
4
  "description": "Flow based programming in javascript, with signals and effects",
5
5
  "main": "src/flow.mjs",
6
6
  "type": "module",
@@ -2,7 +2,7 @@
2
2
  * Default renderers for data binding
3
3
  * Will be used unless overriden in the SimplyBind options parameter
4
4
  */
5
- import { signal as domSignal } from './dom.mjs'
5
+ import { signal as domSignal, trackDomField, trackDomList } from './dom.mjs'
6
6
  import { throttledEffect, effect, untracked, batch } from './state.mjs'
7
7
  import { getValueByPath } from './bind.mjs'
8
8
  /**
@@ -211,35 +211,7 @@ export function arrayByTemplates(context)
211
211
  }
212
212
  }
213
213
  if (this.options.twoway) {
214
- const s = domSignal(context.element, {
215
- childList: true
216
- })
217
- throttledEffect(() => {
218
- const children = Array.from(s.children)
219
- batch(() => {
220
- untracked(() => {
221
- let key=0
222
- const currentList = context.value.slice()
223
- for (const item of children) {
224
- if (item.tagName==='TEMPLATE') {
225
- continue
226
- }
227
- if (item.dataset.flowKey) {
228
- if (item.dataset.flowKey!=key) {
229
- setValueByPath(this.options.root, context.path+'.'+key,
230
- currentList[item.dataset.flowKey])
231
- }
232
- key++
233
- }
234
- }
235
- if (context.value.length>key) {
236
- // remove extra values
237
- const source = getValueByPath(this.options.root, context.path)
238
- source.length = key
239
- }
240
- })
241
- })
242
- })
214
+ trackDomList.call(this, context.element)
243
215
  }
244
216
  }
245
217
 
@@ -488,8 +460,6 @@ export function meta(context)
488
460
  }
489
461
  }
490
462
 
491
- const domSignals = new WeakMap()
492
-
493
463
  /**
494
464
  * sets the innerHTML and title and id properties of any HTML element
495
465
  */
@@ -508,29 +478,8 @@ export function element(context, ...extraprops)
508
478
  const props = ['innerHTML','title','id','className'].concat(extraprops)
509
479
  setProperties(el, value, ...props)
510
480
  if (this.options.twoway) {
511
- batch(() => {
512
- updateProperties.call(this, context, props, valueIsString)
513
- })
514
- }
515
- }
516
-
517
- export function updateProperties(context, props, valueIsString) {
518
- if (domSignals.has(context.element)) {
519
- return
481
+ trackDomField.call(this, context.element, props, valueIsString)
520
482
  }
521
- const s = domSignal(context.element)
522
- domSignals.set(context.element, s)
523
- //TODO: run reverse transformers (extract)
524
- throttledEffect(() => {
525
- let updateValue = s.innerHTML //incorrect: in an anchor this could be s.href
526
- if (!valueIsString) {
527
- updateValue = getProperties(s, ...props)
528
- }
529
- untracked(() => {
530
- // don't trigger this effect when the data changes (root.path)
531
- setValueByPath(this.options.root, context.path, updateValue)
532
- })
533
- })
534
483
  }
535
484
 
536
485
  /**
package/src/dom.mjs CHANGED
@@ -1,4 +1,9 @@
1
- import { signals, signal as stateSignal, notifyGet, notifySet, makeContext } from './state.mjs'
1
+ import { signals, signal as stateSignal, notifyGet, notifySet, makeContext,
2
+ throttledEffect, effect, untracked, batch } from './state.mjs'
3
+ import { getValueByPath } from './bind.mjs'
4
+ import { setValueByPath, getProperties } from './bind.render.mjs'
5
+
6
+ const domSignals = new WeakMap()
2
7
 
3
8
  const domSignalHandler = {
4
9
  get: (target, property, receiver) => {
@@ -108,3 +113,65 @@ function domListen(el, signal, options) {
108
113
  }
109
114
  }
110
115
  }
116
+
117
+ export function trackDomList(element)
118
+ {
119
+ const path = this.getBindingPath(element)
120
+ if (!path) {
121
+ throw new Error('Could not find binding path for element', { cause: element })
122
+ }
123
+ const s = signal(element, {
124
+ childList: true
125
+ })
126
+ throttledEffect(() => {
127
+ const children = Array.from(s.children)
128
+ untracked(() => { // don't track access to the data, only track dom changes
129
+ batch(() => { // apply all changes in the list as one change
130
+ let key=0
131
+ const currentList = getValueByPath(this.options.root, path)
132
+ const source = currentList.slice() // make sure changes in currentList don't affect the original source
133
+ for (const item of children) {
134
+ if (item.tagName==='TEMPLATE') {
135
+ continue
136
+ }
137
+ if (item.dataset.flowKey) { //FIXME: could be other attribute name
138
+ if (item.dataset.flowKey!=key) {
139
+ setValueByPath(this.options.root, path+'.'+key,
140
+ source[item.dataset.flowKey])
141
+ }
142
+ key++
143
+ }
144
+ }
145
+ if (currentList.length>key) {
146
+ // remove extra values
147
+ currentList.length = key
148
+ }
149
+ })
150
+ })
151
+ })
152
+ }
153
+
154
+ export function trackDomField(element, props, valueIsString) {
155
+ if (domSignals.has(element)) {
156
+ return
157
+ }
158
+ const path = this.getBindingPath(element)
159
+ if (!path) {
160
+ throw new Error('Could not find binding path for element', { cause: element })
161
+ }
162
+ const s = signal(element)
163
+ domSignals.set(element, s)
164
+ //TODO: run reverse transformers (extract)
165
+ batch(() => { // avoids cyclical dependencies - check why
166
+ throttledEffect(() => {
167
+ let updateValue = s.innerHTML //FIXME: incorrect: in an anchor this could be s.href - use extract here
168
+ if (!valueIsString) {
169
+ updateValue = getProperties(s, ...props)
170
+ }
171
+ untracked(() => { // don't track changes in data, only in the dom
172
+ // don't trigger this effect when the data changes (root.path)
173
+ setValueByPath(this.options.root, path, updateValue)
174
+ })
175
+ })
176
+ })
177
+ }