sprae 10.1.1 → 10.1.3

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/core.js CHANGED
@@ -28,6 +28,7 @@ export default function sprae(el, values) {
28
28
  // if element was spraed by :with or :each instruction - skip, otherwise save
29
29
  if (!memo.has(el)) memo.set(el, state);
30
30
 
31
+ // disposer draes all internal elements
31
32
  el[_dispose] = () => {
32
33
  while (disposes.length) disposes.pop()();
33
34
  memo.delete(el);
@@ -84,7 +85,7 @@ const parse = (expr, dir, fn) => {
84
85
 
85
86
  export let compile
86
87
 
87
- // configure signals/compile/differ
88
+ // configure signals/compile
88
89
  // it's more compact than using sprae.signal = signal etc.
89
90
  sprae.use = s => {
90
91
  s.signal && use(s);
package/directive/each.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import sprae, { directive } from "../core.js";
2
- import { _change, _signals } from "../store.js";
3
- import { effect, untracked, computed } from '../signal.js';
2
+ import store, { _change, _signals } from "../store.js";
3
+ import { effect, untracked, computed, signal } from '../signal.js';
4
4
 
5
5
 
6
6
  export const _each = Symbol(":each");
@@ -54,16 +54,19 @@ directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
54
54
  for (; i < newl; i++) {
55
55
  cur[i] = newItems[i]
56
56
  let idx = i,
57
- scope = Object.create(state, {
58
- [itemVar]: { get() { return cur[idx] } },
59
- [idxVar]: { value: keys ? keys[idx] : idx },
60
- }),
57
+ scope = store({}),
61
58
  el = (tpl.content || tpl).cloneNode(true),
62
59
  frag = tpl.content ?
63
60
  // fake fragment to init sprae
64
61
  { children: [...el.children], remove() { this.children.map(el => el.remove()) } } :
65
62
  el;
66
63
 
64
+ // define local scope signals
65
+ Object.assign(scope[_signals], state[_signals], {
66
+ [itemVar]: computed(() => cur[idx]),
67
+ [idxVar]: signal(keys ? keys[idx] : idx)
68
+ });
69
+
67
70
  holder.before(el);
68
71
  sprae(frag, scope);
69
72
 
@@ -80,8 +83,8 @@ directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
80
83
 
81
84
  let planned = 0
82
85
  return effect(() => {
83
- // subscribe to items change (.length)
84
- if (!cur) items.value[_change]?.value
86
+ // subscribe to items change (.length) - we do it every time (not just on init) since preact unsubscribes unused signals
87
+ items.value[_change]?.value
85
88
 
86
89
  // make first render immediately, debounce subsequent renders
87
90
  if (!planned) {
package/directive/ref.js CHANGED
@@ -1,11 +1,11 @@
1
+ import { signal } from "../signal.js";
1
2
  import { directive } from "../core.js";
2
3
  import { _change, _signals } from "../store.js";
3
4
  import { ipol } from './default.js';
4
5
 
5
6
  // ref must be last within primaries, since that must be skipped by :each, but before secondaries
6
7
  directive.ref = (el, expr, state) => {
7
- // defining prop is needed for inherited scope, like :each or :with, since el cannot be signal
8
- Object.defineProperty(state, ipol(expr, state), { value: el })
8
+ state[_signals][ipol(expr, state)] = signal(el)
9
9
  }
10
10
 
11
11
  directive.ref.parse = expr => expr
package/dist/sprae.js CHANGED
@@ -34,7 +34,7 @@ function store(values) {
34
34
  const state = new Proxy(signals, {
35
35
  get: (_, key) => key === _change ? _len : key === _signals ? signals : signals[key]?.valueOf(),
36
36
  set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s || ++_len.value),
37
- deleteProperty: (_, key) => del(signals, key) && _len.value--,
37
+ deleteProperty: (_, key) => (signals[key] && (del(signals, key), _len.value--), 1),
38
38
  ownKeys() {
39
39
  _len.value;
40
40
  return Reflect.ownKeys(signals);
@@ -80,7 +80,7 @@ function list(values) {
80
80
  _len.value = signals.length = Number(key) + 1;
81
81
  return true;
82
82
  },
83
- deleteProperty: (_, key) => (del(signals, key), true)
83
+ deleteProperty: (_, key) => (signals[key] && del(signals, key), 1)
84
84
  });
85
85
  return state;
86
86
  }
@@ -111,15 +111,11 @@ function set(signals, key, v) {
111
111
  }
112
112
  }
113
113
  function del(signals, key) {
114
- const s = signals[key];
115
- if (s) {
116
- const del2 = s[Symbol.dispose];
117
- if (del2)
118
- delete s[Symbol.dispose];
119
- delete signals[key];
120
- del2?.();
121
- return true;
122
- }
114
+ const s = signals[key], del2 = s[Symbol.dispose];
115
+ if (del2)
116
+ delete s[Symbol.dispose];
117
+ delete signals[key];
118
+ del2?.();
123
119
  }
124
120
 
125
121
  // core.js
@@ -290,14 +286,13 @@ directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
290
286
  }
291
287
  for (; i < newl; i++) {
292
288
  cur[i] = newItems[i];
293
- let idx = i, scope = Object.create(state, {
294
- [itemVar]: { get() {
295
- return cur[idx];
296
- } },
297
- [idxVar]: { value: keys2 ? keys2[idx] : idx }
298
- }), el = (tpl.content || tpl).cloneNode(true), frag = tpl.content ? { children: [...el.children], remove() {
289
+ let idx = i, scope = store({}), el = (tpl.content || tpl).cloneNode(true), frag = tpl.content ? { children: [...el.children], remove() {
299
290
  this.children.map((el2) => el2.remove());
300
291
  } } : el;
292
+ Object.assign(scope[_signals], state[_signals], {
293
+ [itemVar]: computed(() => cur[idx]),
294
+ [idxVar]: signal(keys2 ? keys2[idx] : idx)
295
+ });
301
296
  holder.before(el);
302
297
  sprae(frag, scope);
303
298
  ((cur[_signals] ||= [])[i] ||= {})[Symbol.dispose] = () => {
@@ -310,8 +305,7 @@ directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
310
305
  };
311
306
  let planned = 0;
312
307
  return effect(() => {
313
- if (!cur)
314
- items.value[_change]?.value;
308
+ items.value[_change]?.value;
315
309
  if (!planned) {
316
310
  update();
317
311
  queueMicrotask(() => (planned && update(), planned = 0));
@@ -497,7 +491,7 @@ var ipol = (v, state) => {
497
491
 
498
492
  // directive/ref.js
499
493
  directive.ref = (el, expr, state) => {
500
- Object.defineProperty(state, ipol(expr, state), { value: el });
494
+ state[_signals][ipol(expr, state)] = signal(el);
501
495
  };
502
496
  directive.ref.parse = (expr) => expr;
503
497
 
package/dist/sprae.min.js CHANGED
@@ -1 +1 @@
1
- var e,t,r,l,n,s=Object.defineProperty,a=Symbol("signals"),o=Symbol("length");function i(t){if(!t)return t;if(t[a])return t;if(Array.isArray(t))return function(t){let r;if(t[a])return t;let l=e(t.length),n=Array(t.length).fill(null);const s=new Proxy(n,{get:(s,c)=>"symbol"==typeof c?c===o?l:c===a?n:n[c]:"length"===c?Array.prototype[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)=>(u(n,t),!0)});return s}(t);if(t.constructor!==Object)return t;let r={},l=e(Object.values(t).length);const s=new Proxy(r,{get:(e,t)=>t===o?l:t===a?r:r[t]?.valueOf(),set:(e,t,n,s)=>(s=r[t],c(r,t,n),s||++l.value),deleteProperty:(e,t)=>u(r,t)&&l.value--,ownKeys:()=>(l.value,Reflect.ownKeys(r))});for(let e in t){const l=Object.getOwnPropertyDescriptor(t,e);l?.get?(r[e]=n(l.get.bind(s)))._set=l.set?.bind(s):(r[e]=null,c(r,e,t[e]))}return s}function c(t,n,s){let a=t[n];if(a)if(s===a.peek());else if(a._set)a._set(s);else if(Array.isArray(s)&&Array.isArray(a.peek())){const e=a.peek();e[o]?r((()=>{l((()=>{let t=0,r=s.length;for(;t<r;t++)e[t]=s[t];e.length=r}))})):a.value=s}else a.value=i(s);else t[n]=a=s?.peek?s:e(i(s))}function u(e,t){const r=e[t];if(r){const l=r[Symbol.dispose];return l&&delete r[Symbol.dispose],delete e[t],l?.(),!0}}var f=Symbol.dispose||=Symbol("dispose"),p={},d=new WeakMap;function y(e,t){if(!e?.children)return;if(d.has(e))return Object.assign(d.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=p[n]||p.default,a=e(t,(e.parse||b)(s.value,b),r,n);a&&l.push(a)}if(d.has(t))return l.push(t[f]);if(t.parentNode!==n)return}else e++}for(let r of[...t.children])e(r,t)}(e),d.has(e)||d.set(e,r),e[f]=()=>{for(;l.length;)l.pop()();d.delete(e)},r}var v,h={},b=(e,t,r)=>{if(r=h[e=e.trim()])return r;try{r=v(e)}catch(r){throw Object.assign(r,{message:`∴ ${r.message}\n\n${t}${e?`="${e}"\n\n`:""}`,expr:e})}return h[e]=r};y.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&&(v=s.compile)};var g,m,k={};((e,t)=>{for(var r in t)s(e,r,{get:t[r],enumerable:!0})})(k,{batch:()=>O,computed:()=>w,effect:()=>S,signal:()=>A,untracked:()=>N});var A=(e,t,r=new Set)=>((t={get value(){return g?.deps.push(r.add(g)),e},set value(t){if(t!==e){e=t;for(let e of r)m?m.add(e):e()}},peek:()=>e}).toJSON=t.then=t.toString=t.valueOf=()=>t.value,t),S=(e,t,r,l)=>(l=(r=l=>{t?.call?.(),l=g,g=r;try{t=e()}finally{g=l}}).deps=[],r(),e=>{for(t?.call?.();e=l.pop();)e.delete(r)}),w=(e,t=A(),r,l)=>((r={get value(){return l||=S((()=>t.value=e())),t.value},peek:t.peek}).toJSON=r.then=r.toString=r.valueOf=()=>r.value,r),O=e=>{let t=m;t||(m=new Set);try{e()}finally{if(!t){t=m,m=null;for(const e of t)e()}}},N=(e,t,r)=>(t=g,g=null,r=e(),g=t,r),j=Symbol(":each");p.each=(e,[l,s,i],c)=>{const u=e[j]=document.createTextNode("");e.replaceWith(u);let f,p,d=0;const v=n((()=>{p=null;let e=i(c);return"number"==typeof e&&(e=Array.from({length:e},((e,t)=>t+1))),e?.constructor===Object&&(p=Object.keys(e),e=Object.values(e)),e||[]})),h=()=>{r((()=>{let t=0,r=v.value,n=r.length;if(f&&!f[o]){for(let e of f[a]||[])e[Symbol.dispose]();f=null,d=0}if(n<d)f.length=n;else{if(f)for(;t<d;t++)f[t]=r[t];else f=r;for(;t<n;t++){f[t]=r[t];let n=t,o=Object.create(c,{[l]:{get:()=>f[n]},[s]:{value:p?p[n]:n}}),i=(e.content||e).cloneNode(!0),d=e.content?{children:[...i.children],remove(){this.children.map((e=>e.remove()))}}:i;u.before(i),y(d,o),((f[a]||=[])[t]||={})[Symbol.dispose]=()=>{d[Symbol.dispose](),d.remove()}}}d=n}))};let b=0;return t((()=>{f||v.value[o]?.value,b?b++:(h(),queueMicrotask((()=>(b&&h(),b=0))))}))},p.each.parse=(e,t)=>{let[r,l]=e.split(/\s+in\s+/),[n,s="$"]=r.split(/\s*,\s*/);return[n,s,t(l)]};var x=Symbol("if");p.if=(e,r,l)=>{let n,s,a,o=e.parentNode,i=e.nextElementSibling,c=document.createTextNode(""),u=[];return e.after(c),e.content?(n=u,e.remove(),s=[...e.content.childNodes]):s=n=[e],i?.hasAttribute(":else")?(i.removeAttribute(":else"),i.hasAttribute(":if")?a=u:(i.remove(),a=i.content?[...i.content.childNodes]:[i])):a=u,t((()=>{const t=r(l)?s:e[x]?u:a;if(i&&(i[x]=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)o.insertBefore(e,c),y(e,l)}}))},p.default=(e,r,l,n)=>{let s,a=n.startsWith("on")&&n.slice(2);return t(a?()=>(s?.(),s=$(e,a,r(l))):()=>{let t=r(l);if(n)T(e,n,D(t,l));else for(let r in t)T(e,_(r),D(t[r],l))})};var $=(e,t,r=(()=>{}))=>{const l={evt:"",target:e,test:()=>!0};l.evt=t.replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,r="")=>(l.test=E[t]?.(l,...r.split("-"))||l.test,"")));const{evt:n,target:s,test:a,defer:o,stop:i,prevent:c,...u}=l;o&&(r=o(r));const f=e=>a(e)&&(i&&e.stopPropagation(),c&&e.preventDefault(),r.call(s,e));return s.addEventListener(n,f,u),()=>s.removeEventListener(n,f,u)},E={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},throttle(e,t){e.defer=e=>C(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=>P.ctrl(e)&&t.every((t=>P[t]?P[t](e):e.key===t)),shift:(e,...t)=>e=>P.shift(e)&&t.every((t=>P[t]?P[t](e):e.key===t)),alt:(e,...t)=>e=>P.alt(e)&&t.every((t=>P[t]?P[t](e):e.key===t)),meta:(e,...t)=>e=>P.meta(e)&&t.every((t=>P[t]?P[t](e):e.key===t)),arrow:()=>P.arrow,enter:()=>P.enter,escape:()=>P.escape,tab:()=>P.tab,space:()=>P.space,backspace:()=>P.backspace,delete:()=>P.delete,digit:()=>P.digit,letter:()=>P.letter,character:()=>P.character},P={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)},T=(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))},W=(e,t)=>{let r;return l=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(l)}),t)}},_=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),D=(e,t)=>e?.replace?e.replace(/\$<([^>]+)>/g,((e,r)=>t[r]??"")):e;p.ref=(e,t,r)=>{Object.defineProperty(r,D(t,r),{value:e})},p.ref.parse=e=>e,p.with=(e,r,l)=>{let n;return t((()=>{let t=r(l);if(n)Object.assign(n,t);else{n=i({}),Object.assign(n[a],l[a]);for(let e in t)n[a][e]=null,n[e]=t[e];y(e,n)}}))},p.html=(e,t,r)=>{let l=t(r);if(!l)return;let n=(l.content||l).cloneNode(!0);e.replaceChildren(n),y(e,r)},p.text=(e,r,l)=>(e.content&&e.replaceWith(e=document.createTextNode("")),t((()=>{let t=r(l);e.textContent=null==t?"":t}))),p.class=(e,r,l)=>{let n=new Set;return t((()=>{let t=r(l),s=new Set;t&&("string"==typeof t?D(t,l).split(" ").map((e=>s.add(e))):Array.isArray(t)?t.map((e=>(e=D(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)}))},p.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+D(t,l));else{e.setAttribute("style",n);for(let r in t)e.style.setProperty(r,D(t[r],l))}}))},p.value=(e,r,l)=>{let n,s,a="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,T(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((()=>a(r(l))))},p.fx=(e,r,l)=>t((()=>r(l))),y.use(k),y.use({compile:e=>y.constructor("__scope",`with (__scope) { return ${e} };`)});var K=y;export{K as default};
1
+ var e,t,r,l,n,s=Object.defineProperty,a=Symbol("signals"),o=Symbol("length");function i(t){if(!t)return t;if(t[a])return t;if(Array.isArray(t))return function(t){let r;if(t[a])return t;let l=e(t.length),n=Array(t.length).fill(null);const s=new Proxy(n,{get:(s,c)=>"symbol"==typeof c?c===o?l:c===a?n:n[c]:"length"===c?Array.prototype[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]&&u(n,t),1)});return s}(t);if(t.constructor!==Object)return t;let r={},l=e(Object.values(t).length);const s=new Proxy(r,{get:(e,t)=>t===o?l:t===a?r:r[t]?.valueOf(),set:(e,t,n,s)=>(s=r[t],c(r,t,n),s||++l.value),deleteProperty:(e,t)=>(r[t]&&(u(r,t),l.value--),1),ownKeys:()=>(l.value,Reflect.ownKeys(r))});for(let e in t){const l=Object.getOwnPropertyDescriptor(t,e);l?.get?(r[e]=n(l.get.bind(s)))._set=l.set?.bind(s):(r[e]=null,c(r,e,t[e]))}return s}function c(t,n,s){let a=t[n];if(a)if(s===a.peek());else if(a._set)a._set(s);else if(Array.isArray(s)&&Array.isArray(a.peek())){const e=a.peek();e[o]?r((()=>{l((()=>{let t=0,r=s.length;for(;t<r;t++)e[t]=s[t];e.length=r}))})):a.value=s}else a.value=i(s);else t[n]=a=s?.peek?s:e(i(s))}function u(e,t){const r=e[t],l=r[Symbol.dispose];l&&delete r[Symbol.dispose],delete e[t],l?.()}var f=Symbol.dispose||=Symbol("dispose"),p={},d=new WeakMap;function y(e,t){if(!e?.children)return;if(d.has(e))return Object.assign(d.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=p[n]||p.default,a=e(t,(e.parse||g)(s.value,g),r,n);a&&l.push(a)}if(d.has(t))return l.push(t[f]);if(t.parentNode!==n)return}else e++}for(let r of[...t.children])e(r,t)}(e),d.has(e)||d.set(e,r),e[f]=()=>{for(;l.length;)l.pop()();d.delete(e)},r}var v,h={},g=(e,t,r)=>{if(r=h[e=e.trim()])return r;try{r=v(e)}catch(r){throw Object.assign(r,{message:`∴ ${r.message}\n\n${t}${e?`="${e}"\n\n`:""}`,expr:e})}return h[e]=r};y.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&&(v=s.compile)};var m,b,k={};((e,t)=>{for(var r in t)s(e,r,{get:t[r],enumerable:!0})})(k,{batch:()=>O,computed:()=>w,effect:()=>S,signal:()=>A,untracked:()=>N});var A=(e,t,r=new Set)=>((t={get value(){return m?.deps.push(r.add(m)),e},set value(t){if(t!==e){e=t;for(let e of r)b?b.add(e):e()}},peek:()=>e}).toJSON=t.then=t.toString=t.valueOf=()=>t.value,t),S=(e,t,r,l)=>(l=(r=l=>{t?.call?.(),l=m,m=r;try{t=e()}finally{m=l}}).deps=[],r(),e=>{for(t?.call?.();e=l.pop();)e.delete(r)}),w=(e,t=A(),r,l)=>((r={get value(){return l||=S((()=>t.value=e())),t.value},peek:t.peek}).toJSON=r.then=r.toString=r.valueOf=()=>r.value,r),O=e=>{let t=b;t||(b=new Set);try{e()}finally{if(!t){t=b,b=null;for(const e of t)e()}}},N=(e,t,r)=>(t=m,m=null,r=e(),m=t,r),x=Symbol(":each");p.each=(l,[s,c,u],f)=>{const p=l[x]=document.createTextNode("");l.replaceWith(p);let d,v,h=0;const g=n((()=>{v=null;let e=u(f);return"number"==typeof e&&(e=Array.from({length:e},((e,t)=>t+1))),e?.constructor===Object&&(v=Object.keys(e),e=Object.values(e)),e||[]})),m=()=>{r((()=>{let t=0,r=g.value,u=r.length;if(d&&!d[o]){for(let e of d[a]||[])e[Symbol.dispose]();d=null,h=0}if(u<h)d.length=u;else{if(d)for(;t<h;t++)d[t]=r[t];else d=r;for(;t<u;t++){d[t]=r[t];let o=t,u=i({}),h=(l.content||l).cloneNode(!0),g=l.content?{children:[...h.children],remove(){this.children.map((e=>e.remove()))}}:h;Object.assign(u[a],f[a],{[s]:n((()=>d[o])),[c]:e(v?v[o]:o)}),p.before(h),y(g,u),((d[a]||=[])[t]||={})[Symbol.dispose]=()=>{g[Symbol.dispose](),g.remove()}}}h=u}))};let b=0;return t((()=>{g.value[o]?.value,b?b++:(m(),queueMicrotask((()=>(b&&m(),b=0))))}))},p.each.parse=(e,t)=>{let[r,l]=e.split(/\s+in\s+/),[n,s="$"]=r.split(/\s*,\s*/);return[n,s,t(l)]};var j=Symbol("if");p.if=(e,r,l)=>{let n,s,a,o=e.parentNode,i=e.nextElementSibling,c=document.createTextNode(""),u=[];return e.after(c),e.content?(n=u,e.remove(),s=[...e.content.childNodes]):s=n=[e],i?.hasAttribute(":else")?(i.removeAttribute(":else"),i.hasAttribute(":if")?a=u:(i.remove(),a=i.content?[...i.content.childNodes]:[i])):a=u,t((()=>{const t=r(l)?s:e[j]?u:a;if(i&&(i[j]=t===s),n!=t){n[0]?.[x]&&(n=[n[0][x]]);for(let e of n)e.remove();n=t;for(let e of n)o.insertBefore(e,c),y(e,l)}}))},p.default=(e,r,l,n)=>{let s,a=n.startsWith("on")&&n.slice(2);return t(a?()=>(s?.(),s=$(e,a,r(l))):()=>{let t=r(l);if(n)C(e,n,D(t,l));else for(let r in t)C(e,_(r),D(t[r],l))})};var $=(e,t,r=(()=>{}))=>{const l={evt:"",target:e,test:()=>!0};l.evt=t.replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,r="")=>(l.test=E[t]?.(l,...r.split("-"))||l.test,"")));const{evt:n,target:s,test:a,defer:o,stop:i,prevent:c,...u}=l;o&&(r=o(r));const f=e=>a(e)&&(i&&e.stopPropagation(),c&&e.preventDefault(),r.call(s,e));return s.addEventListener(n,f,u),()=>s.removeEventListener(n,f,u)},E={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},throttle(e,t){e.defer=e=>P(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=>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,escape:()=>T.escape,tab:()=>T.tab,space:()=>T.space,backspace:()=>T.backspace,delete:()=>T.delete,digit:()=>T.digit,letter:()=>T.letter,character:()=>T.character},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,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)},C=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},P=(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))},W=(e,t)=>{let r;return l=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(l)}),t)}},_=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),D=(e,t)=>e?.replace?e.replace(/\$<([^>]+)>/g,((e,r)=>t[r]??"")):e;p.ref=(t,r,l)=>{l[a][D(r,l)]=e(t)},p.ref.parse=e=>e,p.with=(e,r,l)=>{let n;return t((()=>{let t=r(l);if(n)Object.assign(n,t);else{n=i({}),Object.assign(n[a],l[a]);for(let e in t)n[a][e]=null,n[e]=t[e];y(e,n)}}))},p.html=(e,t,r)=>{let l=t(r);if(!l)return;let n=(l.content||l).cloneNode(!0);e.replaceChildren(n),y(e,r)},p.text=(e,r,l)=>(e.content&&e.replaceWith(e=document.createTextNode("")),t((()=>{let t=r(l);e.textContent=null==t?"":t}))),p.class=(e,r,l)=>{let n=new Set;return t((()=>{let t=r(l),s=new Set;t&&("string"==typeof t?D(t,l).split(" ").map((e=>s.add(e))):Array.isArray(t)?t.map((e=>(e=D(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)}))},p.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+D(t,l));else{e.setAttribute("style",n);for(let r in t)e.style.setProperty(r,D(t[r],l))}}))},p.value=(e,r,l)=>{let n,s,a="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,C(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((()=>a(r(l))))},p.fx=(e,r,l)=>t((()=>r(l))),y.use(k),y.use({compile:e=>y.constructor("__scope",`with (__scope) { return ${e} };`)});var K=y;export{K as default};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sprae",
3
3
  "description": "DOM microhydration.",
4
- "version": "10.1.1",
4
+ "version": "10.1.3",
5
5
  "main": "./sprae.js",
6
6
  "module": "./sprae.js",
7
7
  "type": "module",
package/readme.md CHANGED
@@ -358,10 +358,14 @@ To destroy state and detach sprae handlers, call `element[Symbol.dispose]()`. --
358
358
 
359
359
  ## Justification
360
360
 
361
- [Template-parts](https://github.com/dy/template-parts) is stuck with native HTML quirks ([parsing table](https://github.com/github/template-parts/issues/24), [SVG attributes](https://github.com/github/template-parts/issues/25), [liquid syntax](https://shopify.github.io/liquid/tags/template/#raw) conflict etc).<br/>
362
- [Alpine](https://github.com/alpinejs/alpine) / [petite-vue](https://github.com/vuejs/petite-vue) / [lucia](https://github.com/aidenyabi/lucia) escape native HTML quirks, but have excessive API (`:`, `x-`, `{}`, `@`, `$`) and tend to [self-encapsulate](https://github.com/alpinejs/alpine/discussions/3223).
363
-
364
- _Sprae_ holds open & minimalistic philosophy, combining _`:`-directives_ with _signals_.
361
+ * [Template-parts](https://github.com/dy/template-parts) is stuck with native HTML quirks ([parsing table](https://github.com/github/template-parts/issues/24), [SVG attributes](https://github.com/github/template-parts/issues/25), [liquid syntax](https://shopify.github.io/liquid/tags/template/#raw) conflict etc).
362
+ * [Alpine](https://github.com/alpinejs/alpine) / [petite-vue](https://github.com/vuejs/petite-vue) / [lucia](https://github.com/aidenyabi/lucia) escape native HTML quirks, but have excessive API (`:`, `x-`, `{}`, `@`, `$`), tend to [self-encapsulate](https://github.com/alpinejs/alpine/discussions/3223) and not care about size/performance.
363
+
364
+ _Sprae_ holds open & minimalistic philosophy:
365
+ * Slim `:` API and _signals_ reactivity.
366
+ * Pluggable directives & configurable internals.
367
+ * Small, safe & performant.
368
+ * Aims at making developers happy 🫰
365
369
 
366
370
  <!--
367
371
  | | [AlpineJS](https://github.com/alpinejs/alpine) | [Petite-Vue](https://github.com/vuejs/petite-vue) | Sprae |
package/store.js CHANGED
@@ -23,7 +23,7 @@ export default function store(values) {
23
23
  const state = new Proxy(signals, {
24
24
  get: (_, key) => key === _change ? _len : key === _signals ? signals : signals[key]?.valueOf(),
25
25
  set: (_, key, v, s) => (s = signals[key], set(signals, key, v), s || (++_len.value)), // bump length for new signal
26
- deleteProperty: (_, key) => del(signals, key) && _len.value--,
26
+ deleteProperty: (_, key) => (signals[key] && (del(signals, key), _len.value--), 1),
27
27
  ownKeys() {
28
28
  // subscribe to length when object is spread
29
29
  _len.value
@@ -83,10 +83,12 @@ export function list(values) {
83
83
  },
84
84
 
85
85
  set(_, key, v) {
86
+ // console.log('set', key, v)
86
87
  // .length
87
88
  if (key === 'length') {
88
89
  // force cleaning up tail
89
90
  for (let i = v, l = signals.length; i < l; i++) delete state[i]
91
+ // .length = N directly
90
92
  _len.value = signals.length = v;
91
93
  return true
92
94
  }
@@ -99,7 +101,7 @@ export function list(values) {
99
101
  return true
100
102
  },
101
103
 
102
- deleteProperty: (_, key) => (del(signals, key), true),
104
+ deleteProperty: (_, key) => (signals[key] && del(signals, key), 1),
103
105
 
104
106
  })
105
107
 
@@ -142,13 +144,8 @@ function set(signals, key, v) {
142
144
 
143
145
  // delete signal
144
146
  function del(signals, key) {
145
- // console.log('delete', key)
146
- const s = signals[key]
147
- if (s) {
148
- const del = s[Symbol.dispose]
149
- if (del) delete s[Symbol.dispose]
150
- delete signals[key]
151
- del?.()
152
- return true
153
- }
147
+ const s = signals[key], del = s[Symbol.dispose]
148
+ if (del) delete s[Symbol.dispose]
149
+ delete signals[key]
150
+ del?.()
154
151
  }