sprae 3.0.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/sprae.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/state.js
2
2
  var currentFx;
3
- var currentBatch;
3
+ var batch = /* @__PURE__ */ new Set();
4
+ var pendingUpdate;
4
5
  var targetFxs = /* @__PURE__ */ new WeakMap();
5
6
  var targetProxy = /* @__PURE__ */ new WeakMap();
6
7
  var proxyTarget = /* @__PURE__ */ new WeakMap();
@@ -55,7 +56,8 @@ var handler = {
55
56
  let propFxs = targetFxs.get(target)?.[prop];
56
57
  if (propFxs)
57
58
  for (let fx2 of propFxs)
58
- currentBatch ? currentBatch.add(fx2) : fx2.call();
59
+ batch.add(fx2);
60
+ planUpdate();
59
61
  return true;
60
62
  },
61
63
  deleteProperty(target, prop) {
@@ -85,14 +87,16 @@ var fx = (fn) => {
85
87
  call();
86
88
  return call;
87
89
  };
88
- var batch = (fn) => {
89
- let prevBatch = currentBatch;
90
- currentBatch = /* @__PURE__ */ new Set();
91
- fn();
92
- for (let fx2 of currentBatch)
93
- fx2.call();
94
- currentBatch.clear();
95
- currentBatch = prevBatch;
90
+ var planUpdate = () => {
91
+ if (!pendingUpdate) {
92
+ pendingUpdate = true;
93
+ queueMicrotask(() => {
94
+ for (let fx2 of batch)
95
+ fx2.call();
96
+ batch.clear();
97
+ pendingUpdate = false;
98
+ });
99
+ }
96
100
  };
97
101
 
98
102
  // src/domdiff.js
@@ -208,8 +212,8 @@ primary["if"] = (el, expr) => {
208
212
  }
209
213
  };
210
214
  };
211
- primary["with"] = (el, expr, rootState) => {
212
- let evaluate = parseExpr(el, expr, "with");
215
+ primary["scope"] = (el, expr, rootState) => {
216
+ let evaluate = parseExpr(el, expr, "scope");
213
217
  const localState = evaluate(rootState);
214
218
  let state2 = state(localState, rootState);
215
219
  sprae(el, state2);
@@ -322,22 +326,6 @@ secondary["text"] = (el, expr) => {
322
326
  el.textContent = value == null ? "" : value;
323
327
  };
324
328
  };
325
- secondary["data"] = (el, expr) => {
326
- let evaluate = parseExpr(el, expr, ":data");
327
- return (state2) => {
328
- let value = evaluate(state2);
329
- for (let key in value)
330
- el.dataset[key] = value[key];
331
- };
332
- };
333
- secondary["aria"] = (el, expr) => {
334
- let evaluate = parseExpr(el, expr, ":aria");
335
- const update = (value) => {
336
- for (let key in value)
337
- attr(el, "aria-" + dashcase(key), value[key] == null ? null : value[key] + "");
338
- };
339
- return (state2) => update(evaluate(state2));
340
- };
341
329
  secondary[""] = (el, expr) => {
342
330
  let evaluate = parseExpr(el, expr, ":");
343
331
  if (evaluate)
@@ -569,11 +557,8 @@ var memo = /* @__PURE__ */ new WeakMap();
569
557
  function sprae(container, values) {
570
558
  if (!container.children)
571
559
  return;
572
- if (memo.has(container)) {
573
- let state3 = memo.get(container);
574
- batch(() => Object.assign(state3, values));
575
- return state3;
576
- }
560
+ if (memo.has(container))
561
+ return Object.assign(memo.get(container), values);
577
562
  const state2 = state(values || {});
578
563
  const updates = [];
579
564
  const init = (el, parent = el.parentNode) => {
@@ -626,6 +611,8 @@ function sprae(container, values) {
626
611
 
627
612
  // src/index.js
628
613
  var src_default = sprae;
614
+ if (document.currentScript)
615
+ sprae(document.documentElement);
629
616
  export {
630
617
  src_default as default
631
618
  };
package/sprae.min.js CHANGED
@@ -1 +1 @@
1
- var e,t,r=new WeakMap,n=new WeakMap,l=new WeakMap,s=Symbol("parent"),a={Array:Array,Object:Object,Number:Number,String:String,Boolean:Boolean,Date:Date,console:console},i={has:()=>!0,get(t,l){if("symbol"==typeof l)return t[l];if(!(l in t))return t[s]?.[l];if(Array.isArray(t)&&l in Array.prototype)return t[l];let a=t[l];if(e){let n=r.get(t);n||r.set(t,n={}),n[l]?n[l].includes(e)||n[l].push(e):n[l]=[e]}if(a&&a.constructor===Object||Array.isArray(a)){let e=n.get(a);return e||n.set(a,e=new Proxy(a,i)),e}return a},set(e,n,l){if(!(n in e)&&e[s]&&n in e[s])return e[s][n]=l;if(Array.isArray(e)&&n in Array.prototype)return e[n]=l;const a=e[n];if(Object.is(a,l))return!0;e[n]=l;let i=r.get(e)?.[n];if(i)for(let e of i)t?t.add(e):e.call();return!0},deleteProperty:(e,t)=>(e[t]=void 0,delete e[t],!0)},o=(e,t)=>{if(n.has(e))return n.get(e);if(l.has(e))return e;let r=new Proxy(e,i);return n.set(e,r),l.set(r,e),e[s]=t?o(t):a,r},u=t=>{const r=()=>{let n=e;e=r,t(),e=n};return r(),r},c=new WeakMap,f=class extends Map{#e=new FinalizationRegistry((e=>super.delete(e)));get size(){return[...this].length}constructor(e=[]){super();for(const[t,r]of e)this.set(t,r)}get(e){return super.get(e)?.deref()}set(e,t){let r=super.get(e);return r&&this.#e.unregister(r),r=(e=>c.get(e)||(e=>{const t=new WeakRef(e);return c.set(e,t),t})(e))(t),this.#e.register(t,e,r),super.set(e,r)}},p={},y={};p.if=(e,t)=>{let r=document.createTextNode(""),n=[W(e,t,":if")],l=[e],s=e;for(;(s=e.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(t=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),l.push(s),n.push(W(e,t,":else :if"))):(s.remove(),l.push(s),n.push((()=>1)));return e.replaceWith(s=r),e=>{let t=n.findIndex((t=>t(e)));l[t]!=s&&((s[h]||s).replaceWith(s=l[t]||r),j(s,e))}},p.with=(e,t,r)=>{const n=W(e,t,"with")(r);j(e,o(n,r))};var h=Symbol(":each");p.each=(e,t)=>{let r=function(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=e.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!r)return;let n=r[2].trim(),l=r[1].replace(/^\s*\(|\)\s*$/g,"").trim(),s=l.match(t);return s?[l.replace(t,"").trim(),s[1].trim(),n]:[l,"",n]}(t);if(!r)return x(new Error,e,t);const n=e[h]=document.createTextNode("");e.replaceWith(n);const l=W(e,r[2],":each"),s=e.getAttribute(":key"),a=s?W(null,s):null;e.removeAttribute(":key");const i=e.getAttribute(":ref"),u=new f,c=new f;let p=[];return s=>{let f=l(s);f?"number"==typeof f?f=Array.from({length:f},((e,t)=>[t,t+1])):Array.isArray(f)?f=f.map(((e,t)=>[t+1,e])):"object"==typeof f?f=Object.entries(f):x(Error("Bad list value"),e,t,":each"):f=[];let y=[],h=[];for(let[t,n]of f){let l,f,p=a?.({[r[0]]:n,[r[1]]:t});null==p?l=e.cloneNode(!0):(l=c.get(p))||c.set(p,l=e.cloneNode(!0)),y.push(l),null!=p&&(f=u.get(p))?f[r[0]]=n:(f=o({[r[0]]:n,[i||""]:null,[r[1]]:t},s),null!=p&&u.set(p,f)),h.push(f)}!function(e,t,r,n){const l=new Map,s=new Map;let a,i;for(a=0;a<t.length;a++)l.set(t[a],a);for(a=0;a<r.length;a++)s.set(r[a],a);for(a=i=0;a!==t.length||i!==r.length;){var o=t[a],u=r[i];if(null===o)a++;else if(r.length<=i)e.removeChild(t[a]),a++;else if(t.length<=a)e.insertBefore(u,t[a]||n),i++;else if(o===u)a++,i++;else{var c=s.get(o),f=l.get(u);void 0===c?(e.removeChild(t[a]),a++):void 0===f?(e.insertBefore(u,t[a]||n),i++):(e.insertBefore(t[f],t[a]||n),t[f]=null,f>a+1&&a++,i++)}}}(n.parentNode,p,y,n),p=y;for(let e=0;e<y.length;e++)j(y[e],h[e])}},y.ref=(e,t,r)=>{r[t]=e},y.id=(e,t)=>{let r=W(e,t,":id");return t=>{return n=r(t),e.id=n||0===n?n:"";var n}},y.class=(e,t)=>{let r=W(e,t,":class"),n=e.className;return t=>{let l=r(t),s="string"==typeof l?l:(Array.isArray(l)?l:Object.entries(l).map((([e,t])=>t?e:""))).filter(Boolean).join(" ");e.className=[n,s].filter(Boolean).join(" ")}},y.style=(e,t)=>{let r=W(e,t,":style"),n=e.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),t=>{let l=r(t);if("string"==typeof l)e.setAttribute("style",n+l);else{e.setAttribute("style",n);for(let t in l)e.style.setProperty(t,l[t])}}},y.text=(e,t)=>{let r=W(e,t,":text");return t=>{let n=r(t);e.textContent=null==n?"":n}},y.data=(e,t)=>{let r=W(e,t,":data");return t=>{let n=r(t);for(let t in n)e.dataset[t]=n[t]}},y.aria=(e,t)=>{let r=W(e,t,":aria");return t=>(t=>{for(let r in t)k(e,"aria-"+N(r),null==t[r]?null:t[r]+"")})(r(t))},y[""]=(e,t)=>{let r=W(e,t,":");if(r)return t=>{let n=r(t);for(let t in n)k(e,N(t),n[t])}},y.value=(e,t)=>{let r,n,l=W(e,t,":value"),s="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(r=e.selectionStart,n=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),r&&e.setSelectionRange(r,n)):"checkbox"===e.type?t=>(e.value=t?"on":"",k(e,"checked",t)):"select-one"===e.type?t=>{for(let t in e.options)t.removeAttribute("selected");e.value=t,e.selectedOptions[0]?.setAttribute("selected","")}:t=>e.value=t;return e=>s(l(e))},y.on=(e,t)=>{let r=W(e,t,":on");return t=>{let n=r(t),l=[];for(let t in n)l.push(d(e,t,n[t]));return()=>{for(let e of l)e()}}};var g=(e,t,r,n)=>{let l=n.startsWith("on")&&n.slice(2),s=W(e,t,":"+n);if(s)return l?t=>{let r=s(t)||(()=>{});return d(e,l,r)}:t=>k(e,n,s(t))},d=(e,t,r)=>{if(!r)return;let n=t.split("..").map((t=>{let r={evt:"",target:e,test:()=>!0};return r.evt=(t.startsWith("on")?t.slice(2):t).replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,n="")=>(r.test=m[t]?.(r,...n.split("-"))||r.test,""))),r}));if(1==n.length)return a(r,n[0]);const l=(t,r=0)=>{let s;return s=a((a=>{r&&s();let i=t.call(e,a);"function"!=typeof i&&(i=()=>{}),r+1<n.length&&l(i,r?r+1:1)}),n[r])};let s=l(r);return()=>s();function a(e,{evt:t,target:r,test:n,defer:l,stop:s,prevent:a,...i}){l&&(e=l(e));let o=t=>n(t)&&(s&&t.stopPropagation(),a&&t.preventDefault(),e.call(r,t));return r.addEventListener(t,o,i),()=>r.removeEventListener(t,o,i)}},m={prevent(e){e.prevent=!0},stop(e){e.stop=!0},once(e){e.once=!0},passive(e){e.passive=!0},capture(e){e.capture=!0},window(e){e.target=window},document(e){e.target=document},toggle(e){e.defer=(t,r)=>n=>r?(r.call?.(e.target,n),r=null):r=t()},throttle(e,t){e.defer=e=>v(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>A(e,t?Number(t)||0:108)},outside:e=>t=>{let r=e.target;return!(r.contains(t.target)||!1===t.target.isConnected||r.offsetWidth<1&&r.offsetHeight<1)},self:e=>t=>t.target===e.target,ctrl:(e,...t)=>e=>b.ctrl(e)&&t.every((t=>b[t]?b[t](e):e.key===t)),shift:(e,...t)=>e=>b.shift(e)&&t.every((t=>b[t]?b[t](e):e.key===t)),alt:(e,...t)=>e=>b.alt(e)&&t.every((t=>b[t]?b[t](e):e.key===t)),meta:(e,...t)=>e=>b.meta(e)&&t.every((t=>b[t]?b[t](e):e.key===t)),arrow:e=>b.arrow,enter:e=>b.enter,escape:e=>b.escape,tab:e=>b.tab,space:e=>b.space,backspace:e=>b.backspace,delete:e=>b.delete,digit:e=>b.digit,letter:e=>b.letter,character:e=>b.character},b={ctrl:e=>e.ctrlKey||"Control"===e.key||"Ctrl"===e.key,shift:e=>e.shiftKey||"Shift"===e.key,alt:e=>e.altKey||"Alt"===e.key,meta:e=>e.metaKey||"Meta"===e.key||"Command"===e.key,arrow:e=>e.key.startsWith("Arrow"),enter:e=>"Enter"===e.key,escape:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,backspace:e=>"Backspace"===e.key,delete:e=>"Delete"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^[a-zA-Z]$/.test(e.key),character:e=>/^\S$/.test(e.key)},v=(e,t)=>{let r,n,l=s=>{r=!0,setTimeout((()=>{if(r=!1,n)return n=!1,l(s),e(s)}),t)};return t=>r?n=!0:(l(t),e(t))},A=(e,t)=>{let r;return n=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(n)}),t)}},k=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},w={};function W(e,t,r){let n=w[t];if(!n){let l=/^[\n\s]*if.*\(.*\)/.test(t)||/\b(let|const)\s/.test(t)&&!r.startsWith(":on")?`(() => {${t}})()`:t;try{n=w[t]=new Function("__scope",`with (__scope) { return ${l.trim()} };`)}catch(n){return x(n,e,t,r)}}return l=>{let s;try{s=n.call(e,l)}catch(n){return x(n,e,t,r)}return s}}function x(e,t,r,n){Object.assign(e,{element:t,expression:r}),console.warn(`∴ ${e.message}\n\n${n}=${r?`"${r}"\n\n`:""}`,t),queueMicrotask((()=>{throw e}),0)}function N(e){return e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase()))}j.globals=a;var S=new WeakMap;function j(e,r){if(!e.children)return;if(S.has(e)){let n=S.get(e);return(e=>{let l=t;t=new Set,Object.assign(n,r);for(let e of t)e.call();t.clear(),t=l})(),n}const n=o(r||{}),l=[],s=(e,t=e.parentNode)=>{for(let r in p){let s=":"+r;if(e.hasAttribute?.(s)){let a=e.getAttribute(s);if(e.removeAttribute(s),l.push(p[r](e,a,n,r)),S.has(e)||e.parentNode!==t)return!1}}if(e.attributes)for(let r=0;r<e.attributes.length;){let s=e.attributes[r];if(":"!==s.name[0]){r++;continue}e.removeAttribute(s.name);let a=s.value,i=s.name.slice(1).split(":");for(let r of i){let s=y[r]||g;if(l.push(s(e,a,n,r)),S.has(e)||e.parentNode!==t)return!1}}for(let t,r=0;t=e.children[r];r++)!1===s(t,e)&&r--};s(e);for(let e of l)if(e){let t;u((()=>{"function"==typeof t&&t(),t=e(n)}))}return S.set(e,n),n}var E=j;export{E as default};
1
+ var e,t,r=new Set,n=new WeakMap,l=new WeakMap,s=new WeakMap,i=Symbol("parent"),a={Array:Array,Object:Object,Number:Number,String:String,Boolean:Boolean,Date:Date,console:console},o={has:()=>!0,get(t,r){if("symbol"==typeof r)return t[r];if(!(r in t))return t[i]?.[r];if(Array.isArray(t)&&r in Array.prototype)return t[r];let s=t[r];if(e){let l=n.get(t);l||n.set(t,l={}),l[r]?l[r].includes(e)||l[r].push(e):l[r]=[e]}if(s&&s.constructor===Object||Array.isArray(s)){let e=l.get(s);return e||l.set(s,e=new Proxy(s,o)),e}return s},set(e,t,l){if(!(t in e)&&e[i]&&t in e[i])return e[i][t]=l;if(Array.isArray(e)&&t in Array.prototype)return e[t]=l;const s=e[t];if(Object.is(s,l))return!0;e[t]=l;let a=n.get(e)?.[t];if(a)for(let e of a)r.add(e);return f(),!0},deleteProperty:(e,t)=>(e[t]=void 0,delete e[t],!0)},u=(e,t)=>{if(l.has(e))return l.get(e);if(s.has(e))return e;let r=new Proxy(e,o);return l.set(e,r),s.set(r,e),e[i]=t?u(t):a,r},c=t=>{const r=()=>{let n=e;e=r,t(),e=n};return r(),r},f=()=>{t||(t=!0,queueMicrotask((()=>{for(let e of r)e.call();r.clear(),t=!1})))},p=new WeakMap,y=class extends Map{#e=new FinalizationRegistry((e=>super.delete(e)));get size(){return[...this].length}constructor(e=[]){super();for(const[t,r]of e)this.set(t,r)}get(e){return super.get(e)?.deref()}set(e,t){let r=super.get(e);return r&&this.#e.unregister(r),r=(e=>p.get(e)||(e=>{const t=new WeakRef(e);return p.set(e,t),t})(e))(t),this.#e.register(t,e,r),super.set(e,r)}},g={},h={};g.if=(e,t)=>{let r=document.createTextNode(""),n=[N(e,t,":if")],l=[e],s=e;for(;(s=e.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(t=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),l.push(s),n.push(N(e,t,":else :if"))):(s.remove(),l.push(s),n.push((()=>1)));return e.replaceWith(s=r),e=>{let t=n.findIndex((t=>t(e)));l[t]!=s&&((s[d]||s).replaceWith(s=l[t]||r),j(s,e))}},g.scope=(e,t,r)=>{const n=N(e,t,"scope")(r);j(e,u(n,r))};var d=Symbol(":each");g.each=(e,t)=>{let r=function(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=e.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!r)return;let n=r[2].trim(),l=r[1].replace(/^\s*\(|\)\s*$/g,"").trim(),s=l.match(t);return s?[l.replace(t,"").trim(),s[1].trim(),n]:[l,"",n]}(t);if(!r)return S(new Error,e,t);const n=e[d]=document.createTextNode("");e.replaceWith(n);const l=N(e,r[2],":each"),s=e.getAttribute(":key"),i=s?N(null,s):null;e.removeAttribute(":key");const a=e.getAttribute(":ref"),o=new y,c=new y;let f=[];return s=>{let p=l(s);p?"number"==typeof p?p=Array.from({length:p},((e,t)=>[t,t+1])):Array.isArray(p)?p=p.map(((e,t)=>[t+1,e])):"object"==typeof p?p=Object.entries(p):S(Error("Bad list value"),e,t,":each"):p=[];let y=[],g=[];for(let[t,n]of p){let l,f,p=i?.({[r[0]]:n,[r[1]]:t});null==p?l=e.cloneNode(!0):(l=c.get(p))||c.set(p,l=e.cloneNode(!0)),y.push(l),null!=p&&(f=o.get(p))?f[r[0]]=n:(f=u({[r[0]]:n,[a||""]:null,[r[1]]:t},s),null!=p&&o.set(p,f)),g.push(f)}!function(e,t,r,n){const l=new Map,s=new Map;let i,a;for(i=0;i<t.length;i++)l.set(t[i],i);for(i=0;i<r.length;i++)s.set(r[i],i);for(i=a=0;i!==t.length||a!==r.length;){var o=t[i],u=r[a];if(null===o)i++;else if(r.length<=a)e.removeChild(t[i]),i++;else if(t.length<=i)e.insertBefore(u,t[i]||n),a++;else if(o===u)i++,a++;else{var c=s.get(o),f=l.get(u);void 0===c?(e.removeChild(t[i]),i++):void 0===f?(e.insertBefore(u,t[i]||n),a++):(e.insertBefore(t[f],t[i]||n),t[f]=null,f>i+1&&i++,a++)}}}(n.parentNode,f,y,n),f=y;for(let e=0;e<y.length;e++)j(y[e],g[e])}},h.ref=(e,t,r)=>{r[t]=e},h.id=(e,t)=>{let r=N(e,t,":id");return t=>{return n=r(t),e.id=n||0===n?n:"";var n}},h.class=(e,t)=>{let r=N(e,t,":class"),n=e.className;return t=>{let l=r(t),s="string"==typeof l?l:(Array.isArray(l)?l:Object.entries(l).map((([e,t])=>t?e:""))).filter(Boolean).join(" ");e.className=[n,s].filter(Boolean).join(" ")}},h.style=(e,t)=>{let r=N(e,t,":style"),n=e.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),t=>{let l=r(t);if("string"==typeof l)e.setAttribute("style",n+l);else{e.setAttribute("style",n);for(let t in l)e.style.setProperty(t,l[t])}}},h.text=(e,t)=>{let r=N(e,t,":text");return t=>{let n=r(t);e.textContent=null==n?"":n}},h[""]=(e,t)=>{let r=N(e,t,":");if(r)return t=>{let n=r(t);for(let t in n)W(e,t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),n[t])}},h.value=(e,t)=>{let r,n,l=N(e,t,":value"),s="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(r=e.selectionStart,n=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),r&&e.setSelectionRange(r,n)):"checkbox"===e.type?t=>(e.value=t?"on":"",W(e,"checked",t)):"select-one"===e.type?t=>{for(let t in e.options)t.removeAttribute("selected");e.value=t,e.selectedOptions[0]?.setAttribute("selected","")}:t=>e.value=t;return e=>s(l(e))},h.on=(e,t)=>{let r=N(e,t,":on");return t=>{let n=r(t),l=[];for(let t in n)l.push(b(e,t,n[t]));return()=>{for(let e of l)e()}}};var m=(e,t,r,n)=>{let l=n.startsWith("on")&&n.slice(2),s=N(e,t,":"+n);if(s)return l?t=>{let r=s(t)||(()=>{});return b(e,l,r)}:t=>W(e,n,s(t))},b=(e,t,r)=>{if(!r)return;let n=t.split("..").map((t=>{let r={evt:"",target:e,test:()=>!0};return r.evt=(t.startsWith("on")?t.slice(2):t).replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,n="")=>(r.test=v[t]?.(r,...n.split("-"))||r.test,""))),r}));if(1==n.length)return i(r,n[0]);const l=(t,r=0)=>{let s;return s=i((i=>{r&&s();let a=t.call(e,i);"function"!=typeof a&&(a=()=>{}),r+1<n.length&&l(a,r?r+1:1)}),n[r])};let s=l(r);return()=>s();function i(e,{evt:t,target:r,test:n,defer:l,stop:s,prevent:i,...a}){l&&(e=l(e));let o=t=>n(t)&&(s&&t.stopPropagation(),i&&t.preventDefault(),e.call(r,t));return r.addEventListener(t,o,a),()=>r.removeEventListener(t,o,a)}},v={prevent(e){e.prevent=!0},stop(e){e.stop=!0},once(e){e.once=!0},passive(e){e.passive=!0},capture(e){e.capture=!0},window(e){e.target=window},document(e){e.target=document},toggle(e){e.defer=(t,r)=>n=>r?(r.call?.(e.target,n),r=null):r=t()},throttle(e,t){e.defer=e=>k(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>w(e,t?Number(t)||0:108)},outside:e=>t=>{let r=e.target;return!(r.contains(t.target)||!1===t.target.isConnected||r.offsetWidth<1&&r.offsetHeight<1)},self:e=>t=>t.target===e.target,ctrl:(e,...t)=>e=>A.ctrl(e)&&t.every((t=>A[t]?A[t](e):e.key===t)),shift:(e,...t)=>e=>A.shift(e)&&t.every((t=>A[t]?A[t](e):e.key===t)),alt:(e,...t)=>e=>A.alt(e)&&t.every((t=>A[t]?A[t](e):e.key===t)),meta:(e,...t)=>e=>A.meta(e)&&t.every((t=>A[t]?A[t](e):e.key===t)),arrow:e=>A.arrow,enter:e=>A.enter,escape:e=>A.escape,tab:e=>A.tab,space:e=>A.space,backspace:e=>A.backspace,delete:e=>A.delete,digit:e=>A.digit,letter:e=>A.letter,character:e=>A.character},A={ctrl:e=>e.ctrlKey||"Control"===e.key||"Ctrl"===e.key,shift:e=>e.shiftKey||"Shift"===e.key,alt:e=>e.altKey||"Alt"===e.key,meta:e=>e.metaKey||"Meta"===e.key||"Command"===e.key,arrow:e=>e.key.startsWith("Arrow"),enter:e=>"Enter"===e.key,escape:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,backspace:e=>"Backspace"===e.key,delete:e=>"Delete"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^[a-zA-Z]$/.test(e.key),character:e=>/^\S$/.test(e.key)},k=(e,t)=>{let r,n,l=s=>{r=!0,setTimeout((()=>{if(r=!1,n)return n=!1,l(s),e(s)}),t)};return t=>r?n=!0:(l(t),e(t))},w=(e,t)=>{let r;return n=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(n)}),t)}},W=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},x={};function N(e,t,r){let n=x[t];if(!n){let l=/^[\n\s]*if.*\(.*\)/.test(t)||/\b(let|const)\s/.test(t)&&!r.startsWith(":on")?`(() => {${t}})()`:t;try{n=x[t]=new Function("__scope",`with (__scope) { return ${l.trim()} };`)}catch(n){return S(n,e,t,r)}}return l=>{let s;try{s=n.call(e,l)}catch(n){return S(n,e,t,r)}return s}}function S(e,t,r,n){Object.assign(e,{element:t,expression:r}),console.warn(`∴ ${e.message}\n\n${n}=${r?`"${r}"\n\n`:""}`,t),queueMicrotask((()=>{throw e}),0)}j.globals=a;var E=new WeakMap;function j(e,t){if(!e.children)return;if(E.has(e))return Object.assign(E.get(e),t);const r=u(t||{}),n=[],l=(e,t=e.parentNode)=>{for(let l in g){let s=":"+l;if(e.hasAttribute?.(s)){let i=e.getAttribute(s);if(e.removeAttribute(s),n.push(g[l](e,i,r,l)),E.has(e)||e.parentNode!==t)return!1}}if(e.attributes)for(let l=0;l<e.attributes.length;){let s=e.attributes[l];if(":"!==s.name[0]){l++;continue}e.removeAttribute(s.name);let i=s.value,a=s.name.slice(1).split(":");for(let l of a){let s=h[l]||m;if(n.push(s(e,i,r,l)),E.has(e)||e.parentNode!==t)return!1}}for(let t,r=0;t=e.children[r];r++)!1===l(t,e)&&r--};l(e);for(let e of n)if(e){let t;c((()=>{"function"==typeof t&&t(),t=e(r)}))}return E.set(e,r),r}var M=j;document.currentScript&&j(document.documentElement);export{M as default};
package/src/core.js CHANGED
@@ -1,4 +1,4 @@
1
- import { state as createState, fx, batch, sandbox } from './state.js';
1
+ import { state as createState, fx, sandbox } from './state.js';
2
2
  import defaultDirective, { primary, secondary } from './directives.js';
3
3
 
4
4
  sprae.globals=sandbox
@@ -7,11 +7,7 @@ sprae.globals=sandbox
7
7
  const memo = new WeakMap
8
8
  export default function sprae(container, values) {
9
9
  if (!container.children) return
10
- if (memo.has(container)) {
11
- let state = memo.get(container)
12
- batch(() => Object.assign(state, values))
13
- return state
14
- }
10
+ if (memo.has(container)) return Object.assign( memo.get(container), values)
15
11
 
16
12
  // subscribe to reactives
17
13
  // for (let prop in values) {
package/src/directives.js CHANGED
@@ -10,8 +10,8 @@ export const primary = {}, secondary = {}
10
10
 
11
11
 
12
12
  // :if is interchangeable with :each depending on order, :if :each or :each :if have different meanings
13
- // as for :if :with - :if must init first, since it is lazy, to avoid initializing component ahead of time by :with
14
- // we consider :with={x} :if={x} case insignificant
13
+ // as for :if :scope - :if must init first, since it is lazy, to avoid initializing component ahead of time by :scope
14
+ // we consider :scope={x} :if={x} case insignificant
15
15
  primary['if'] = (el, expr) => {
16
16
  let holder = document.createTextNode(''),
17
17
  clauses = [parseExpr(el, expr, ':if')],
@@ -44,9 +44,9 @@ primary['if'] = (el, expr) => {
44
44
  }
45
45
  }
46
46
 
47
- // :with must come before :each, but :if has primary importance
48
- primary['with'] = (el, expr, rootState) => {
49
- let evaluate = parseExpr(el, expr, 'with')
47
+ // :scope must come before :each, but :if has primary importance
48
+ primary['scope'] = (el, expr, rootState) => {
49
+ let evaluate = parseExpr(el, expr, 'scope')
50
50
  const localState = evaluate(rootState)
51
51
  let state = createState(localState, rootState)
52
52
  // console.log(123, state.foo, state.bar)
@@ -187,23 +187,6 @@ secondary['text'] = (el, expr) => {
187
187
  }
188
188
  }
189
189
 
190
- secondary['data'] = (el, expr) => {
191
- let evaluate = parseExpr(el, expr, ':data')
192
-
193
- return ((state) => {
194
- let value = evaluate(state)
195
- for (let key in value) el.dataset[key] = value[key];
196
- })
197
- }
198
-
199
- secondary['aria'] = (el, expr) => {
200
- let evaluate = parseExpr(el, expr, ':aria')
201
- const update = (value) => {
202
- for (let key in value) attr(el, 'aria-' + dashcase(key), value[key] == null ? null : value[key] + '');
203
- }
204
- return ((state) => update(evaluate(state)))
205
- }
206
-
207
190
  // set props in-bulk or run effect
208
191
  secondary[''] = (el, expr) => {
209
192
  let evaluate = parseExpr(el, expr, ':')
package/src/index.js CHANGED
@@ -3,8 +3,4 @@ import './directives.js';
3
3
  export default sprae;
4
4
 
5
5
  // autoinit
6
- // NOTE: abandoning for now, since requires a separate non-module JS entry, until use-case appears
7
- // const s = document.currentScript
8
- // if (s && s.hasAttribute('init')) {
9
- // sprae(document.documentElement)
10
- // }
6
+ if (document.currentScript) sprae(document.documentElement)
package/src/state.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // currentFx stack of listeners
2
- let currentFx, currentBatch
2
+ let currentFx, batch = new Set, pendingUpdate
3
3
 
4
4
  const targetFxs = new WeakMap
5
5
  const targetProxy = new WeakMap
@@ -60,7 +60,8 @@ const handler = {
60
60
  // whenever target prop is set, call all dependent fxs
61
61
  let propFxs = targetFxs.get(target)?.[prop]
62
62
 
63
- if (propFxs) for (let fx of propFxs) currentBatch ? currentBatch.add(fx) : fx.call()
63
+ if (propFxs) for (let fx of propFxs) batch.add(fx)
64
+ planUpdate()
64
65
 
65
66
  // FIXME: unsubscribe / delete effects by setting null/undefined
66
67
  // if (value == null) targetFxs.delete(prev)
@@ -103,11 +104,13 @@ export const fx = (fn) => {
103
104
  return call
104
105
  }
105
106
 
106
- export const batch = fn => {
107
- let prevBatch = currentBatch
108
- currentBatch = new Set
109
- fn()
110
- for (let fx of currentBatch) fx.call()
111
- currentBatch.clear()
112
- currentBatch = prevBatch
113
- }
107
+ export const planUpdate = () => {
108
+ if (!pendingUpdate) {
109
+ pendingUpdate = true
110
+ queueMicrotask(() => {
111
+ for (let fx of batch) fx.call()
112
+ batch.clear()
113
+ pendingUpdate = false
114
+ })
115
+ }
116
+ }