sprae 10.4.1 → 10.6.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.
@@ -88,11 +88,8 @@ const mods = {
88
88
  shift: (_, ...param) => (e) => keys.shift(e) && param.every((p) => (keys[p] ? keys[p](e) : e.key === p)),
89
89
  alt: (_, ...param) => (e) => keys.alt(e) && param.every((p) => (keys[p] ? keys[p](e) : e.key === p)),
90
90
  meta: (_, ...param) => (e) => keys.meta(e) && param.every((p) => (keys[p] ? keys[p](e) : e.key === p)),
91
+ // NOTE: we don't expose up/left/right/down as too verbose: can and better be handled/differentiated at once
91
92
  arrow: () => keys.arrow,
92
- up: () => keys.up,
93
- left: () => keys.left,
94
- right: () => keys.right,
95
- down: () => keys.down,
96
93
  enter: () => keys.enter,
97
94
  esc: () => keys.esc,
98
95
  tab: () => keys.tab,
@@ -110,10 +107,6 @@ const keys = {
110
107
  alt: (e) => e.altKey || e.key === "Alt",
111
108
  meta: (e) => e.metaKey || e.key === "Meta" || e.key === "Command",
112
109
  arrow: (e) => e.key.startsWith("Arrow"),
113
- up: (e) => e.key === "ArrowUp",
114
- left: (e) => e.key === "ArrowLeft",
115
- right: (e) => e.key === "ArrowRight",
116
- down: (e) => e.key === "ArrowDown",
117
110
  enter: (e) => e.key === "Enter",
118
111
  esc: (e) => e.key.startsWith("Esc"),
119
112
  tab: (e) => e.key === "Tab",
package/dist/sprae.js CHANGED
@@ -33,7 +33,7 @@ function store(values, parent) {
33
33
  let signals = { ...parent?.[_signals] }, _len = signal(Object.values(values).length);
34
34
  const state = new Proxy(signals, {
35
35
  get: (_, key) => key === _change ? _len : key === _signals ? signals : signals[key]?.valueOf(),
36
- set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s || ++_len.value),
36
+ set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s ?? ++_len.value),
37
37
  deleteProperty: (_, key) => (signals[key] && (del(signals, key), _len.value--), 1),
38
38
  ownKeys() {
39
39
  _len.value;
@@ -45,7 +45,7 @@ function store(values, parent) {
45
45
  if (desc?.get) {
46
46
  (signals[key] = computed(desc.get.bind(state)))._set = desc.set?.bind(state);
47
47
  } else {
48
- signals[key] = null;
48
+ signals[key] = void 0;
49
49
  set(signals, key, values[key]);
50
50
  }
51
51
  }
@@ -56,7 +56,7 @@ function list(values) {
56
56
  let lastProp;
57
57
  if (values[_signals])
58
58
  return values;
59
- let _len = signal(values.length), signals = Array(values.length).fill(null);
59
+ let _len = signal(values.length), signals = Array(values.length).fill();
60
60
  const state = new Proxy(signals, {
61
61
  get(_, key) {
62
62
  if (typeof key === "symbol")
@@ -87,7 +87,9 @@ function list(values) {
87
87
  }
88
88
  function set(signals, key, v) {
89
89
  let s = signals[key];
90
- if (!s) {
90
+ if (key[0] === "_")
91
+ signals[key] = v;
92
+ else if (!s) {
91
93
  signals[key] = s = v?.peek ? v : signal(store(v));
92
94
  } else if (v === s.peek())
93
95
  ;
@@ -443,10 +445,6 @@ var mods = {
443
445
  alt: (_, ...param) => (e) => keys.alt(e) && param.every((p) => keys[p] ? keys[p](e) : e.key === p),
444
446
  meta: (_, ...param) => (e) => keys.meta(e) && param.every((p) => keys[p] ? keys[p](e) : e.key === p),
445
447
  arrow: () => keys.arrow,
446
- up: () => keys.up,
447
- left: () => keys.left,
448
- right: () => keys.right,
449
- down: () => keys.down,
450
448
  enter: () => keys.enter,
451
449
  esc: () => keys.esc,
452
450
  tab: () => keys.tab,
@@ -462,10 +460,6 @@ var keys = {
462
460
  alt: (e) => e.altKey || e.key === "Alt",
463
461
  meta: (e) => e.metaKey || e.key === "Meta" || e.key === "Command",
464
462
  arrow: (e) => e.key.startsWith("Arrow"),
465
- up: (e) => e.key === "ArrowUp",
466
- left: (e) => e.key === "ArrowLeft",
467
- right: (e) => e.key === "ArrowRight",
468
- down: (e) => e.key === "ArrowDown",
469
463
  enter: (e) => e.key === "Enter",
470
464
  esc: (e) => e.key.startsWith("Esc"),
471
465
  tab: (e) => e.key === "Tab",
package/dist/sprae.min.js CHANGED
@@ -1 +1 @@
1
- var e,t,r,l,n,o=Object.defineProperty,s=Symbol("signals"),a=Symbol("length");function i(t,r){if(!t)return t;if(t[s])return t;if(Array.isArray(t))return function(t){let r;if(t[s])return t;let l=e(t.length),n=Array(t.length).fill(null);const o=new Proxy(n,{get:(o,c)=>"symbol"==typeof c?c===a?l:c===s?n:n[c]:"length"===c?u[r]?l.peek():l.value:(r=c,n[c]?n[c].valueOf():c<n.length?(n[c]=e(i(t[c]))).value:void 0),set(e,t,r){if("length"===t){for(let e=r,t=n.length;e<t;e++)delete o[e];return l.value=n.length=r,!0}return c(n,t,r),t>=l.peek()&&(l.value=n.length=Number(t)+1),!0},deleteProperty:(e,t)=>(n[t]&&f(n,t),1)});return o}(t);if(t.constructor!==Object)return t;let l={...r?.[s]},o=e(Object.values(t).length);const p=new Proxy(l,{get:(e,t)=>t===a?o:t===s?l:l[t]?.valueOf(),set:(e,t,r,n)=>(n=l[t],c(l,t,r),n||++o.value),deleteProperty:(e,t)=>(l[t]&&(f(l,t),o.value--),1),ownKeys:()=>(o.value,Reflect.ownKeys(l))});for(let e in t){const r=Object.getOwnPropertyDescriptor(t,e);r?.get?(l[e]=n(r.get.bind(p)))._set=r.set?.bind(p):(l[e]=null,c(l,e,t[e]))}return p}var u={push:1,pop:1,shift:1,unshift:1,splice:1};function c(t,n,o){let s=t[n];if(s)if(o===s.peek());else if(s._set)s._set(o);else if(Array.isArray(o)&&Array.isArray(s.peek())){const e=s.peek();e[a]?r((()=>{l((()=>{let t=0,r=o.length;for(;t<r;t++)e[t]=o[t];e.length=r}))})):s.value=o}else s.value=i(o);else t[n]=s=o?.peek?o:e(i(o))}function f(e,t){const r=e[t],l=r[Symbol.dispose];l&&delete r[Symbol.dispose],delete e[t],l?.()}var p=Symbol.dispose||=Symbol("dispose"),d={},y=new WeakMap;function h(e,t){if(!e?.children)return;if(y.has(e))return Object.assign(y.get(e),t);const r=i(t||{}),l=[];return function e(t,n=t.parentNode){if(t.attributes)for(let e=0;e<t.attributes.length;){let o=t.attributes[e];if(":"===o.name[0]){t.removeAttribute(o.name);let e=o.name.slice(1).split(":");for(let n of e){let e=d[n]||d.default,s=e(t,(e.parse||g)(o.value,g),r,n);s&&l.push(s)}if(y.has(t))return l.push(t[p]);if(t.parentNode!==n)return}else e++}for(let r of[...t.children])e(r,t)}(e),y.has(e)||y.set(e,r),e[p]=()=>{for(;l.length;)l.pop()();y.delete(e)},r}var m,v={},g=(e,t,r)=>{if(r=v[e=e.trim()])return r;try{r=m(e)}catch(r){b(r,t,e)}return v[e]=r},b=(e,t,r="")=>{throw Object.assign(e,{message:`∴ ${e.message}\n\n${t}${r?`="${r}"\n\n`:""}`,expr:r})};h.use=o=>{o.signal&&function(o){e=o.signal,t=o.effect,n=o.computed,l=o.batch||(e=>e()),r=o.untracked||l}(o),o.compile&&(m=o.compile)};var k,w,A={};((e,t)=>{for(var r in t)o(e,r,{get:t[r],enumerable:!0})})(A,{batch:()=>x,computed:()=>N,effect:()=>O,signal:()=>S,untracked:()=>$});var S=(e,t,r=new Set)=>((t={get value(){return k?.deps.push(r.add(k)),e},set value(t){if(t!==e){e=t;for(let e of r)w?w.add(e):e()}},peek:()=>e}).toJSON=t.then=t.toString=t.valueOf=()=>t.value,t),O=(e,t,r,l)=>(l=(r=l=>{t?.call?.(),l=k,k=r;try{t=e()}finally{k=l}}).deps=[],r(),e=>{for(t?.call?.();e=l.pop();)e.delete(r)}),N=(e,t=S(),r,l)=>((r={get value(){return l||=O((()=>t.value=e())),t.value},peek:t.peek}).toJSON=r.then=r.toString=r.valueOf=()=>r.value,r),x=e=>{let t=w;t||(w=new Set);try{e()}finally{if(!t){t=w,w=null;for(const e of t)e()}}},$=(e,t,r)=>(t=k,k=null,r=e(),k=t,r),j=Symbol(":each");d.each=(e,[l,o,u],c)=>{const f=e[j]=document.createTextNode("");e.replaceWith(f);let p,d,y=0;const m=n((()=>{d=null;let e=u(c);return"number"==typeof e&&(e=Array.from({length:e},((e,t)=>t+1))),e?.constructor===Object&&(d=Object.keys(e),e=Object.values(e)),e||[]})),v=()=>{r((()=>{let t=0,r=m.value,n=r.length;if(p&&!p[a]){for(let e of p[s]||[])e[Symbol.dispose]();p=null,y=0}if(n<y)p.length=n;else{if(p)for(;t<y;t++)p[t]=r[t];else p=r;for(;t<n;t++){p[t]=r[t];let n=t,a=i({[l]:p[s]?.[n]||p[n],[o]:d?d[n]:n},c),u=(e.content||e).cloneNode(!0),y=e.content?{children:[...u.children],remove(){this.children.map((e=>e.remove()))}}:u;f.before(u),h(y,a),((p[s]||=[])[t]||={})[Symbol.dispose]=()=>{y[Symbol.dispose](),y.remove()}}}y=n}))};let g=0;return t((()=>{m.value[a]?.value,g?g++:(v(),queueMicrotask((()=>(g&&v(),g=0))))}))},d.each.parse=(e,t)=>{let[r,l]=e.split(/\s+in\s+/),[n,o="$"]=r.split(/\s*,\s*/);return[n,o,t(l)]};var E=Symbol("if");d.if=(e,r,l)=>{let n,o,s,a=e.parentNode,i=e.nextElementSibling,u=document.createTextNode(""),c=[];return e.after(u),e.content?(n=c,e.remove(),o=[...e.content.childNodes]):o=n=[e],i?.hasAttribute(":else")?(i.removeAttribute(":else"),i.hasAttribute(":if")?s=c:(i.remove(),s=i.content?[...i.content.childNodes]:[i])):s=c,t((()=>{const t=r(l)?o:e[E]?c:s;if(i&&(i[E]=t===o),n!=t){n[0]?.[j]&&(n=[n[0][j]]);for(let e of n)e.remove();n=t;for(let e of n)a.insertBefore(e,u),h(e,l)}}))},d.default=(e,r,l,n)=>{if(!n.startsWith("on"))return t((()=>{let t=r(l);if(n)W(e,n,_(t,l));else for(let r in t)W(e,L(r),_(t[r],l))}));const o=n.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,l="")=>(r.test=P[t]?.(r,...l.split("-"))||r.test,""))),r}));if(1==o.length)return t((()=>f(r(l),o[0])));let s,a,i,u=0;const c=e=>{i=f((t=>(i(),a=e?.(t),(u=++u%o.length)?c(a):s&&c(s))),o[u])};return t((()=>(s=r(l),!i&&c(s),()=>s=null)));function f(e,{evt:t,target:r,test:l,defer:n,stop:o,prevent:s,immediate:a,...i}){n&&(e=n(e));const u=r=>{try{l(r)&&(o&&(a?r.stopImmediatePropagation():r.stopPropagation()),s&&r.preventDefault(),e?.(r))}catch(r){b(r,`:on${t}`,e)}};return r.addEventListener(t,u,i),()=>r.removeEventListener(t,u,i)}};var P={prevent(e){e.prevent=!0},stop(e){e.stop=!0},immediate(e){e.immediate=!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},throttle(e,t){e.defer=e=>C(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>D(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=>T.ctrl(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),shift:(e,...t)=>e=>T.shift(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),alt:(e,...t)=>e=>T.alt(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),meta:(e,...t)=>e=>T.meta(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),arrow:()=>T.arrow,up:()=>T.up,left:()=>T.left,right:()=>T.right,down:()=>T.down,enter:()=>T.enter,esc:()=>T.esc,tab:()=>T.tab,space:()=>T.space,delete:()=>T.delete,digit:()=>T.digit,letter:()=>T.letter,char:()=>T.char},T={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"),up:e=>"ArrowUp"===e.key,left:e=>"ArrowLeft"===e.key,right:e=>"ArrowRight"===e.key,down:e=>"ArrowDown"===e.key,enter:e=>"Enter"===e.key,esc:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,delete:e=>"Delete"===e.key||"Backspace"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^\p{L}$/gu.test(e.key),char:e=>/^\S$/.test(e.key)},W=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},C=(e,t)=>{let r,l,n=o=>{r=!0,setTimeout((()=>{if(r=!1,l)return l=!1,n(o),e(o)}),t)};return t=>r?l=!0:(n(t),e(t))},D=(e,t)=>{let r;return l=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(l)}),t)}},L=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),_=(e,t)=>e?.replace?e.replace(/\$<([^>]+)>/g,((e,r)=>t[r]??"")):e;d.ref=(e,t,r)=>{r[_(t,r)]=e},d.ref.parse=e=>e,d.with=(e,r,l)=>{let n;return t((()=>{let t=r(l);h(e,n?t:n=i(t,l))}))},d.html=(e,t,r)=>{let l=t(r);if(!l)return;let n=(l.content||l).cloneNode(!0);e.replaceChildren(n),h(e,r)},d.text=(e,r,l)=>(e.content&&e.replaceWith(e=document.createTextNode("")),t((()=>{let t=r(l);e.textContent=null==t?"":t}))),d.class=(e,r,l)=>{let n=new Set;return t((()=>{let t=r(l),o=new Set;t&&("string"==typeof t?_(t,l).split(" ").map((e=>o.add(e))):Array.isArray(t)?t.map((e=>(e=_(e,l))&&o.add(e))):Object.entries(t).map((([e,t])=>t&&o.add(e))));for(let t of n)o.has(t)?o.delete(t):e.classList.remove(t);for(let t of n=o)e.classList.add(t)}))},d.style=(e,r,l)=>{let n=e.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),t((()=>{let t=r(l);if("string"==typeof t)e.setAttribute("style",n+_(t,l));else{e.setAttribute("style",n);for(let r in t)e.style.setProperty(r,_(t[r],l))}}))},d.value=(e,r,l)=>{let n,o,s="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(n=e.selectionStart,o=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),n&&e.setSelectionRange(n,o)):"checkbox"===e.type?t=>(e.checked=t,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 t((()=>s(r(l))))},d.fx=(e,r,l)=>t((()=>r(l))),h.use(A),h.use({compile:e=>h.constructor("__scope",`with (__scope) { return ${e} };`)});var K=h;export{K as default};
1
+ var e,t,r,l,n,s=Object.defineProperty,o=Symbol("signals"),a=Symbol("length");function i(t,r){if(!t)return t;if(t[o])return t;if(Array.isArray(t))return function(t){let r;if(t[o])return t;let l=e(t.length),n=Array(t.length).fill();const s=new Proxy(n,{get:(s,c)=>"symbol"==typeof c?c===a?l:c===o?n:n[c]:"length"===c?u[r]?l.peek():l.value:(r=c,n[c]?n[c].valueOf():c<n.length?(n[c]=e(i(t[c]))).value:void 0),set(e,t,r){if("length"===t){for(let e=r,t=n.length;e<t;e++)delete s[e];return l.value=n.length=r,!0}return c(n,t,r),t>=l.peek()&&(l.value=n.length=Number(t)+1),!0},deleteProperty:(e,t)=>(n[t]&&f(n,t),1)});return s}(t);if(t.constructor!==Object)return t;let l={...r?.[o]},s=e(Object.values(t).length);const p=new Proxy(l,{get:(e,t)=>t===a?s:t===o?l:l[t]?.valueOf(),set:(e,t,r,n)=>(n=l[t],c(l,t,r),n??++s.value),deleteProperty:(e,t)=>(l[t]&&(f(l,t),s.value--),1),ownKeys:()=>(s.value,Reflect.ownKeys(l))});for(let e in t){const r=Object.getOwnPropertyDescriptor(t,e);r?.get?(l[e]=n(r.get.bind(p)))._set=r.set?.bind(p):(l[e]=void 0,c(l,e,t[e]))}return p}var u={push:1,pop:1,shift:1,unshift:1,splice:1};function c(t,n,s){let o=t[n];if("_"===n[0])t[n]=s;else if(o)if(s===o.peek());else if(o._set)o._set(s);else if(Array.isArray(s)&&Array.isArray(o.peek())){const e=o.peek();e[a]?r((()=>{l((()=>{let t=0,r=s.length;for(;t<r;t++)e[t]=s[t];e.length=r}))})):o.value=s}else o.value=i(s);else t[n]=o=s?.peek?s:e(i(s))}function f(e,t){const r=e[t],l=r[Symbol.dispose];l&&delete r[Symbol.dispose],delete e[t],l?.()}var p=Symbol.dispose||=Symbol("dispose"),d={},y=new WeakMap;function h(e,t){if(!e?.children)return;if(y.has(e))return Object.assign(y.get(e),t);const r=i(t||{}),l=[];return function e(t,n=t.parentNode){if(t.attributes)for(let e=0;e<t.attributes.length;){let s=t.attributes[e];if(":"===s.name[0]){t.removeAttribute(s.name);let e=s.name.slice(1).split(":");for(let n of e){let e=d[n]||d.default,o=e(t,(e.parse||g)(s.value,g),r,n);o&&l.push(o)}if(y.has(t))return l.push(t[p]);if(t.parentNode!==n)return}else e++}for(let r of[...t.children])e(r,t)}(e),y.has(e)||y.set(e,r),e[p]=()=>{for(;l.length;)l.pop()();y.delete(e)},r}var m,v={},g=(e,t,r)=>{if(r=v[e=e.trim()])return r;try{r=m(e)}catch(r){b(r,t,e)}return v[e]=r},b=(e,t,r="")=>{throw Object.assign(e,{message:`∴ ${e.message}\n\n${t}${r?`="${r}"\n\n`:""}`,expr:r})};h.use=s=>{s.signal&&function(s){e=s.signal,t=s.effect,n=s.computed,l=s.batch||(e=>e()),r=s.untracked||l}(s),s.compile&&(m=s.compile)};var k,A,S={};((e,t)=>{for(var r in t)s(e,r,{get:t[r],enumerable:!0})})(S,{batch:()=>x,computed:()=>N,effect:()=>O,signal:()=>w,untracked:()=>$});var w=(e,t,r=new Set)=>((t={get value(){return k?.deps.push(r.add(k)),e},set value(t){if(t!==e){e=t;for(let e of r)A?A.add(e):e()}},peek:()=>e}).toJSON=t.then=t.toString=t.valueOf=()=>t.value,t),O=(e,t,r,l)=>(l=(r=l=>{t?.call?.(),l=k,k=r;try{t=e()}finally{k=l}}).deps=[],r(),e=>{for(t?.call?.();e=l.pop();)e.delete(r)}),N=(e,t=w(),r,l)=>((r={get value(){return l||=O((()=>t.value=e())),t.value},peek:t.peek}).toJSON=r.then=r.toString=r.valueOf=()=>r.value,r),x=e=>{let t=A;t||(A=new Set);try{e()}finally{if(!t){t=A,A=null;for(const e of t)e()}}},$=(e,t,r)=>(t=k,k=null,r=e(),k=t,r),j=Symbol(":each");d.each=(e,[l,s,u],c)=>{const f=e[j]=document.createTextNode("");e.replaceWith(f);let p,d,y=0;const m=n((()=>{d=null;let e=u(c);return"number"==typeof e&&(e=Array.from({length:e},((e,t)=>t+1))),e?.constructor===Object&&(d=Object.keys(e),e=Object.values(e)),e||[]})),v=()=>{r((()=>{let t=0,r=m.value,n=r.length;if(p&&!p[a]){for(let e of p[o]||[])e[Symbol.dispose]();p=null,y=0}if(n<y)p.length=n;else{if(p)for(;t<y;t++)p[t]=r[t];else p=r;for(;t<n;t++){p[t]=r[t];let n=t,a=i({[l]:p[o]?.[n]||p[n],[s]:d?d[n]:n},c),u=(e.content||e).cloneNode(!0),y=e.content?{children:[...u.children],remove(){this.children.map((e=>e.remove()))}}:u;f.before(u),h(y,a),((p[o]||=[])[t]||={})[Symbol.dispose]=()=>{y[Symbol.dispose](),y.remove()}}}y=n}))};let g=0;return t((()=>{m.value[a]?.value,g?g++:(v(),queueMicrotask((()=>(g&&v(),g=0))))}))},d.each.parse=(e,t)=>{let[r,l]=e.split(/\s+in\s+/),[n,s="$"]=r.split(/\s*,\s*/);return[n,s,t(l)]};var E=Symbol("if");d.if=(e,r,l)=>{let n,s,o,a=e.parentNode,i=e.nextElementSibling,u=document.createTextNode(""),c=[];return e.after(u),e.content?(n=c,e.remove(),s=[...e.content.childNodes]):s=n=[e],i?.hasAttribute(":else")?(i.removeAttribute(":else"),i.hasAttribute(":if")?o=c:(i.remove(),o=i.content?[...i.content.childNodes]:[i])):o=c,t((()=>{const t=r(l)?s:e[E]?c:o;if(i&&(i[E]=t===s),n!=t){n[0]?.[j]&&(n=[n[0][j]]);for(let e of n)e.remove();n=t;for(let e of n)a.insertBefore(e,u),h(e,l)}}))},d.default=(e,r,l,n)=>{if(!n.startsWith("on"))return t((()=>{let t=r(l);if(n)W(e,n,K(t,l));else for(let r in t)W(e,D(r),K(t[r],l))}));const s=n.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,l="")=>(r.test=P[t]?.(r,...l.split("-"))||r.test,""))),r}));if(1==s.length)return t((()=>f(r(l),s[0])));let o,a,i,u=0;const c=e=>{i=f((t=>(i(),a=e?.(t),(u=++u%s.length)?c(a):o&&c(o))),s[u])};return t((()=>(o=r(l),!i&&c(o),()=>o=null)));function f(e,{evt:t,target:r,test:l,defer:n,stop:s,prevent:o,immediate:a,...i}){n&&(e=n(e));const u=r=>{try{l(r)&&(s&&(a?r.stopImmediatePropagation():r.stopPropagation()),o&&r.preventDefault(),e?.(r))}catch(r){b(r,`:on${t}`,e)}};return r.addEventListener(t,u,i),()=>r.removeEventListener(t,u,i)}};var P={prevent(e){e.prevent=!0},stop(e){e.stop=!0},immediate(e){e.immediate=!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},throttle(e,t){e.defer=e=>C(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>_(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=>T.ctrl(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),shift:(e,...t)=>e=>T.shift(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),alt:(e,...t)=>e=>T.alt(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),meta:(e,...t)=>e=>T.meta(e)&&t.every((t=>T[t]?T[t](e):e.key===t)),arrow:()=>T.arrow,enter:()=>T.enter,esc:()=>T.esc,tab:()=>T.tab,space:()=>T.space,delete:()=>T.delete,digit:()=>T.digit,letter:()=>T.letter,char:()=>T.char},T={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,esc:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,delete:e=>"Delete"===e.key||"Backspace"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^\p{L}$/gu.test(e.key),char:e=>/^\S$/.test(e.key)},W=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},C=(e,t)=>{let r,l,n=s=>{r=!0,setTimeout((()=>{if(r=!1,l)return l=!1,n(s),e(s)}),t)};return t=>r?l=!0:(n(t),e(t))},_=(e,t)=>{let r;return l=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(l)}),t)}},D=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),K=(e,t)=>e?.replace?e.replace(/\$<([^>]+)>/g,((e,r)=>t[r]??"")):e;d.ref=(e,t,r)=>{r[K(t,r)]=e},d.ref.parse=e=>e,d.with=(e,r,l)=>{let n;return t((()=>{let t=r(l);h(e,n?t:n=i(t,l))}))},d.html=(e,t,r)=>{let l=t(r);if(!l)return;let n=(l.content||l).cloneNode(!0);e.replaceChildren(n),h(e,r)},d.text=(e,r,l)=>(e.content&&e.replaceWith(e=document.createTextNode("")),t((()=>{let t=r(l);e.textContent=null==t?"":t}))),d.class=(e,r,l)=>{let n=new Set;return t((()=>{let t=r(l),s=new Set;t&&("string"==typeof t?K(t,l).split(" ").map((e=>s.add(e))):Array.isArray(t)?t.map((e=>(e=K(e,l))&&s.add(e))):Object.entries(t).map((([e,t])=>t&&s.add(e))));for(let t of n)s.has(t)?s.delete(t):e.classList.remove(t);for(let t of n=s)e.classList.add(t)}))},d.style=(e,r,l)=>{let n=e.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),t((()=>{let t=r(l);if("string"==typeof t)e.setAttribute("style",n+K(t,l));else{e.setAttribute("style",n);for(let r in t)e.style.setProperty(r,K(t[r],l))}}))},d.value=(e,r,l)=>{let n,s,o="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(n=e.selectionStart,s=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),n&&e.setSelectionRange(n,s)):"checkbox"===e.type?t=>(e.checked=t,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 t((()=>o(r(l))))},d.fx=(e,r,l)=>t((()=>r(l))),h.use(S),h.use({compile:e=>h.constructor("__scope",`with (__scope) { return ${e} };`)});var L=h;export{L as default};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sprae",
3
3
  "description": "DOM microhydration.",
4
- "version": "10.4.1",
4
+ "version": "10.6.0",
5
5
  "main": "./sprae.js",
6
6
  "module": "./sprae.js",
7
7
  "type": "module",
package/readme.md CHANGED
@@ -1,4 +1,4 @@
1
- # ∴ spræ [![tests](https://github.com/dy/sprae/actions/workflows/node.js.yml/badge.svg)](https://github.com/dy/sprae/actions/workflows/node.js.yml) [![size](https://img.shields.io/bundlephobia/minzip/sprae?label=size)](https://bundlephobia.com/result?p=sprae) [![npm](https://img.shields.io/npm/v/sprae?color=orange)](https://npmjs.org/sprae)
1
+ # ∴ spræ [![tests](https://github.com/dy/sprae/actions/workflows/node.js.yml/badge.svg)](https://github.com/dy/sprae/actions/workflows/node.js.yml) [![npm package minimized gzipped size](https://img.shields.io/bundlejs/size/sprae)](https://bundlejs.com/?q=sprae) [![npm](https://img.shields.io/npm/v/sprae?color=orange)](https://npmjs.org/sprae)
2
2
 
3
3
  > DOM tree microhydration
4
4
 
@@ -197,32 +197,15 @@ Attach event(s) listener with optional modifiers.
197
197
  * `.window`, `.document`, `.outside`, `.self` – specify event target.
198
198
  * `.throttle-<ms>`, `.debounce-<ms>` – defer function call with one of the methods.
199
199
  * `.<key>` – filtered by [`event.key`](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values):
200
- * `.ctrl`, `.shift`, `.alt`, `.meta`, `.enter`, `.esc`, `.tab`, `.space`, `.up`, `.right`, `.down`, `.left` – direct keys
200
+ * `.ctrl`, `.shift`, `.alt`, `.meta`, `.enter`, `.esc`, `.tab`, `.space` – direct key
201
201
  * `.delete` – delete or backspace
202
- * `.arrow` – up, right, down or left
202
+ * `.arrow` – up, right, down or left arrow
203
203
  * `.digit` – 0-9
204
204
  * `.letter` – A-Z, a-z or any [unicode letter](https://unicode.org/reports/tr18/#General_Category_Property)
205
205
  * `.char` – any non-space character
206
206
  * `.ctrl-<key>, .alt-<key>, .meta-<key>, .shift-<key>` – key combinations, eg. `.ctrl-alt-delete` or `.meta-x`.
207
207
  * `.*` – any other modifier has no effect, but allows binding multiple handlers to same event (like jQuery event classes).
208
208
 
209
- #### `:html="element"` 🔌
210
-
211
- > Include as `import 'sprae/directive/html'`.
212
-
213
- Set html content of an element or instantiate a template.
214
-
215
- ```html
216
- Hello, <span :html="userElement">Guest</span>.
217
-
218
- <!-- fragment -->
219
- Hello, <template :html="user.name">Guest</template>.
220
-
221
- <!-- instantiate template -->
222
- <template :ref="tpl"><span :text="foo"></span></template>
223
- <div :html="tpl" :with="{foo:'bar'}">...inserted here...</div>
224
- ```
225
-
226
209
  #### `:data="values"` 🔌
227
210
 
228
211
  > Include as `import 'sprae/directive/data'`.
@@ -253,6 +236,24 @@ Set `aria-*` attributes. Boolean values are stringified.
253
236
  -->
254
237
  ```
255
238
 
239
+
240
+ #### `:html="element"` 🔌 (experimental)
241
+
242
+ > Include as `import 'sprae/directive/html'`.
243
+
244
+ Set html content of an element or instantiate a template.
245
+
246
+ ```html
247
+ Hello, <span :html="userElement">Guest</span>.
248
+
249
+ <!-- fragment -->
250
+ Hello, <template :html="user.name">Guest</template>.
251
+
252
+ <!-- instantiate template -->
253
+ <template :ref="tpl"><span :text="foo"></span></template>
254
+ <div :html="tpl" :with="{foo:'bar'}">...inserted here...</div>
255
+ ```
256
+
256
257
  <!--
257
258
  #### `:onvisible..oninvisible="e => e => {}"`
258
259
 
@@ -300,8 +301,17 @@ Provider | Size | Feature
300
301
  [`@webreflection/signal`](https://ghib.io/@webreflection/signal) | 531b | Class-based, better performance, good for small-medium states.
301
302
  [`usignal`](https://ghib.io/usignal) | 850b | Class-based with optimizations, good for medium states.
302
303
  [`@preact/signals-core`](https://ghub.io/@preact/signals-core) | 1.47kb | Best performance, good for any states, industry standard.
303
- [`signal-polyfill`](https://github.com/tc39/proposal-signals) | 2.5kb | Proposal signals. Use via [adapter](https://gist.github.com/dy/bbac687464ccf5322ab0e2fd0680dc4d).
304
+ [`signal-polyfill`](https://github.com/proposal-signals/signal-polyfill) | 2.5kb | Proposal signals. Use via [adapter](https://gist.github.com/dy/bbac687464ccf5322ab0e2fd0680dc4d).
304
305
 
306
+ ## Untracked
307
+
308
+ Properties prefixed with `_` indicate untracked value:
309
+
310
+ ```js
311
+ let state = sprae(el, {x:1, _y:2})
312
+ state.x++ // updates template
313
+ state._y++ // no side-effect
314
+ ```
305
315
 
306
316
  ## Evaluator
307
317
 
package/store.js CHANGED
@@ -21,8 +21,8 @@ export default function store(values, parent) {
21
21
 
22
22
  // proxy conducts prop access to signals
23
23
  const state = new Proxy(signals, {
24
- get: (_, key) => key === _change ? _len : key === _signals ? signals : signals[key]?.valueOf(),
25
- set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s || (++_len.value)), // bump length for new signal
24
+ get: (_, key) => key === _change ? _len : key === _signals ? signals : (signals[key]?.valueOf()),
25
+ set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s ?? (++_len.value)), // bump length for new signal
26
26
  deleteProperty: (_, key) => (signals[key] && (del(signals, key), _len.value--), 1),
27
27
  ownKeys() {
28
28
  // subscribe to length when object is spread
@@ -42,7 +42,7 @@ export default function store(values, parent) {
42
42
  }
43
43
  else {
44
44
  // init blank signal - make sure we don't take prototype one
45
- signals[key] = null
45
+ signals[key] = undefined
46
46
  set(signals, key, values[key]);
47
47
  }
48
48
  }
@@ -64,7 +64,7 @@ export function list(values) {
64
64
  // .length signal is stored separately, since it cannot be replaced on array
65
65
  let _len = signal(values.length),
66
66
  // gotta fill with null since proto methods like .reduce may fail
67
- signals = Array(values.length).fill(null);
67
+ signals = Array(values.length).fill();
68
68
 
69
69
  // proxy conducts prop access to signals
70
70
  const state = new Proxy(signals, {
@@ -114,8 +114,10 @@ export function list(values) {
114
114
  function set(signals, key, v) {
115
115
  let s = signals[key]
116
116
 
117
+ // untracked
118
+ if (key[0] === '_') signals[key] = v
117
119
  // new property
118
- if (!s) {
120
+ else if (!s) {
119
121
  // preserve signal value as is
120
122
  signals[key] = s = v?.peek ? v : signal(store(v))
121
123
  }