sprae 10.3.0 → 10.4.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.
@@ -2,28 +2,18 @@ import { directive, err } from "../core.js";
2
2
  import { effect } from "../signal.js";
3
3
 
4
4
  // set generic property directive
5
- directive.default = (el, evaluate, state, name) => {
6
- let evt = name.startsWith("on") && name.slice(2), off
7
- return effect(
8
- evt ?
9
- () => (
10
- off?.(), // intermediate teardown
11
- off = on(el, evt, evaluate(state))
12
- ) :
13
- () => {
14
- let value = evaluate(state);
15
- if (name) attr(el, name, ipol(value, state))
16
- else for (let key in value) attr(el, dashcase(key), ipol(value[key], state));
17
- });
18
- };
19
-
5
+ directive.default = (target, evaluate, state, name) => {
6
+ // simple prop
7
+ if (!name.startsWith('on')) return effect(() => {
8
+ let value = evaluate(state);
9
+ if (name) attr(target, name, ipol(value, state))
10
+ else for (let key in value) attr(target, dashcase(key), ipol(value[key], state));
11
+ });
20
12
 
21
- // bind event to a target
22
- // NOTE: if you decide to remove chain of events, please ask yourself - are you not confident again?
23
- // did you look at someone else again? That's unique selling feature of sprae, don't diminish your own value.
24
- const on = (target, evt, fn = () => { }) => {
13
+ // bind event to a target
14
+ // NOTE: if you decide to remove chain of events, thing again - that's unique feature of sprae, don't diminish your own value.
25
15
  // ona..onb
26
- const ctxs = evt.split('..').map(e => {
16
+ const ctxs = name.split('..').map(e => {
27
17
  let ctx = { evt: '', target, test: () => true };
28
18
  ctx.evt = (e.startsWith('on') ? e.slice(2) : e).replace(/\.(\w+)?-?([-\w]+)?/g,
29
19
  (match, mod, param = '') => (ctx.test = mods[mod]?.(ctx, ...param.split('-')) || ctx.test, '')
@@ -31,35 +21,37 @@ const on = (target, evt, fn = () => { }) => {
31
21
  return ctx;
32
22
  });
33
23
 
34
- // single event bind
35
- if (ctxs.length == 1) return addListener(fn, ctxs[0])
36
-
37
- // events chain cycler
38
- const nextListener = (fn, idx = 0) => {
39
- let off
40
- return off = addListener((e) => {
41
- if (idx) off(); // don't remove entry listener - we must keep chain entry always open
42
- let nextFn = fn.call(target, e)
43
- if (typeof nextFn !== 'function') nextFn = () => { }
44
- if (idx + 1 < ctxs.length) nextListener(nextFn, idx + 1);
45
- }, ctxs[idx]);
24
+ // single event
25
+ if (ctxs.length == 1) return effect(() => addListener(evaluate(state), ctxs[0]))
26
+
27
+ // events cycler
28
+ let startFn, nextFn, off, idx = 0
29
+ const nextListener = (fn) => {
30
+ off = addListener((e) => (
31
+ off(), nextFn = fn?.(e), (idx = ++idx % ctxs.length) ? nextListener(nextFn) : (startFn && nextListener(startFn))
32
+ ), ctxs[idx]);
46
33
  }
47
34
 
48
- return nextListener(fn)
35
+ return effect(() => (
36
+ startFn = evaluate(state),
37
+ !off && nextListener(startFn),
38
+ () => startFn = null // nil startFn to autodispose chain
39
+ ))
49
40
 
50
- // add listener applying the context
51
- function addListener(fn, { evt, target, test, defer, stop, prevent, ...opts }) {
41
+ // add listener with the context
42
+ function addListener(fn, { evt, target, test, defer, stop, prevent, immediate, ...opts }) {
52
43
  if (defer) fn = defer(fn)
53
44
 
54
45
  const cb = (e) => {
55
46
  try {
56
- test(e) && (stop && e.stopPropagation(), prevent && e.preventDefault(), fn.call(target, e))
47
+ test(e) && (stop && (immediate ? e.stopImmediatePropagation() : e.stopPropagation()), prevent && e.preventDefault(), fn?.(e))
57
48
  } catch (error) { err(error, `:on${evt}`, fn) }
58
49
  };
59
50
 
60
51
  target.addEventListener(evt, cb, opts)
61
52
  return () => target.removeEventListener(evt, cb, opts)
62
53
  };
54
+
63
55
  };
64
56
 
65
57
  // event modifiers
@@ -67,6 +59,7 @@ const mods = {
67
59
  // actions
68
60
  prevent(ctx) { ctx.prevent = true; },
69
61
  stop(ctx) { ctx.stop = true; },
62
+ immediate(ctx) { ctx.immediate = true; },
70
63
 
71
64
  // options
72
65
  once(ctx) { ctx.once = true; },
@@ -96,15 +89,18 @@ const mods = {
96
89
  alt: (_, ...param) => (e) => keys.alt(e) && param.every((p) => (keys[p] ? keys[p](e) : e.key === p)),
97
90
  meta: (_, ...param) => (e) => keys.meta(e) && param.every((p) => (keys[p] ? keys[p](e) : e.key === p)),
98
91
  arrow: () => keys.arrow,
92
+ up: () => keys.up,
93
+ left: () => keys.left,
94
+ right: () => keys.right,
95
+ down: () => keys.down,
99
96
  enter: () => keys.enter,
100
- escape: () => keys.escape,
97
+ esc: () => keys.esc,
101
98
  tab: () => keys.tab,
102
99
  space: () => keys.space,
103
- backspace: () => keys.backspace,
104
100
  delete: () => keys.delete,
105
101
  digit: () => keys.digit,
106
102
  letter: () => keys.letter,
107
- character: () => keys.character,
103
+ char: () => keys.char,
108
104
  };
109
105
 
110
106
  // key testers
@@ -114,15 +110,18 @@ const keys = {
114
110
  alt: (e) => e.altKey || e.key === "Alt",
115
111
  meta: (e) => e.metaKey || e.key === "Meta" || e.key === "Command",
116
112
  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
117
  enter: (e) => e.key === "Enter",
118
- escape: (e) => e.key.startsWith("Esc"),
118
+ esc: (e) => e.key.startsWith("Esc"),
119
119
  tab: (e) => e.key === "Tab",
120
120
  space: (e) => e.key === " " || e.key === "Space" || e.key === " ",
121
- backspace: (e) => e.key === "Backspace",
122
- delete: (e) => e.key === "Delete",
121
+ delete: (e) => e.key === "Delete" || e.key === "Backspace",
123
122
  digit: (e) => /^\d$/.test(e.key),
124
123
  letter: (e) => /^[a-zA-Z]$/.test(e.key),
125
- character: (e) => /^\S$/.test(e.key),
124
+ char: (e) => /^\S$/.test(e.key),
126
125
  };
127
126
 
128
127
  // set attr
package/dist/sprae.js CHANGED
@@ -356,22 +356,17 @@ directive.if = (ifEl, evaluate, state) => {
356
356
  };
357
357
 
358
358
  // directive/default.js
359
- directive.default = (el, evaluate, state, name) => {
360
- let evt = name.startsWith("on") && name.slice(2), off;
361
- return effect(
362
- evt ? () => (off?.(), off = on(el, evt, evaluate(state))) : () => {
359
+ directive.default = (target, evaluate, state, name) => {
360
+ if (!name.startsWith("on"))
361
+ return effect(() => {
363
362
  let value = evaluate(state);
364
363
  if (name)
365
- attr(el, name, ipol(value, state));
364
+ attr(target, name, ipol(value, state));
366
365
  else
367
366
  for (let key in value)
368
- attr(el, dashcase(key), ipol(value[key], state));
369
- }
370
- );
371
- };
372
- var on = (target, evt, fn = () => {
373
- }) => {
374
- const ctxs = evt.split("..").map((e) => {
367
+ attr(target, dashcase(key), ipol(value[key], state));
368
+ });
369
+ const ctxs = name.split("..").map((e) => {
375
370
  let ctx = { evt: "", target, test: () => true };
376
371
  ctx.evt = (e.startsWith("on") ? e.slice(2) : e).replace(
377
372
  /\.(\w+)?-?([-\w]+)?/g,
@@ -380,33 +375,24 @@ var on = (target, evt, fn = () => {
380
375
  return ctx;
381
376
  });
382
377
  if (ctxs.length == 1)
383
- return addListener(fn, ctxs[0]);
384
- const nextListener = (fn2, idx = 0) => {
385
- let off;
386
- return off = addListener((e) => {
387
- if (idx)
388
- off();
389
- let nextFn = fn2.call(target, e);
390
- if (typeof nextFn !== "function")
391
- nextFn = () => {
392
- };
393
- if (idx + 1 < ctxs.length)
394
- nextListener(nextFn, idx + 1);
395
- }, ctxs[idx]);
378
+ return effect(() => addListener(evaluate(state), ctxs[0]));
379
+ let startFn, nextFn, off, idx = 0;
380
+ const nextListener = (fn) => {
381
+ off = addListener((e) => (off(), nextFn = fn?.(e), (idx = ++idx % ctxs.length) ? nextListener(nextFn) : startFn && nextListener(startFn)), ctxs[idx]);
396
382
  };
397
- return nextListener(fn);
398
- function addListener(fn2, { evt: evt2, target: target2, test, defer, stop, prevent, ...opts }) {
383
+ return effect(() => (startFn = evaluate(state), !off && nextListener(startFn), () => startFn = null));
384
+ function addListener(fn, { evt, target: target2, test, defer, stop, prevent, immediate, ...opts }) {
399
385
  if (defer)
400
- fn2 = defer(fn2);
386
+ fn = defer(fn);
401
387
  const cb = (e) => {
402
388
  try {
403
- test(e) && (stop && e.stopPropagation(), prevent && e.preventDefault(), fn2.call(target2, e));
389
+ test(e) && (stop && (immediate ? e.stopImmediatePropagation() : e.stopPropagation()), prevent && e.preventDefault(), fn?.(e));
404
390
  } catch (error) {
405
- err(error, `:on${evt2}`, fn2);
391
+ err(error, `:on${evt}`, fn);
406
392
  }
407
393
  };
408
- target2.addEventListener(evt2, cb, opts);
409
- return () => target2.removeEventListener(evt2, cb, opts);
394
+ target2.addEventListener(evt, cb, opts);
395
+ return () => target2.removeEventListener(evt, cb, opts);
410
396
  }
411
397
  ;
412
398
  };
@@ -417,6 +403,9 @@ var mods = {
417
403
  stop(ctx) {
418
404
  ctx.stop = true;
419
405
  },
406
+ immediate(ctx) {
407
+ ctx.immediate = true;
408
+ },
420
409
  once(ctx) {
421
410
  ctx.once = true;
422
411
  },
@@ -454,15 +443,18 @@ var mods = {
454
443
  alt: (_, ...param) => (e) => keys.alt(e) && param.every((p) => keys[p] ? keys[p](e) : e.key === p),
455
444
  meta: (_, ...param) => (e) => keys.meta(e) && param.every((p) => keys[p] ? keys[p](e) : e.key === p),
456
445
  arrow: () => keys.arrow,
446
+ up: () => keys.up,
447
+ left: () => keys.left,
448
+ right: () => keys.right,
449
+ down: () => keys.down,
457
450
  enter: () => keys.enter,
458
- escape: () => keys.escape,
451
+ esc: () => keys.esc,
459
452
  tab: () => keys.tab,
460
453
  space: () => keys.space,
461
- backspace: () => keys.backspace,
462
454
  delete: () => keys.delete,
463
455
  digit: () => keys.digit,
464
456
  letter: () => keys.letter,
465
- character: () => keys.character
457
+ char: () => keys.char
466
458
  };
467
459
  var keys = {
468
460
  ctrl: (e) => e.ctrlKey || e.key === "Control" || e.key === "Ctrl",
@@ -470,15 +462,18 @@ var keys = {
470
462
  alt: (e) => e.altKey || e.key === "Alt",
471
463
  meta: (e) => e.metaKey || e.key === "Meta" || e.key === "Command",
472
464
  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",
473
469
  enter: (e) => e.key === "Enter",
474
- escape: (e) => e.key.startsWith("Esc"),
470
+ esc: (e) => e.key.startsWith("Esc"),
475
471
  tab: (e) => e.key === "Tab",
476
472
  space: (e) => e.key === "\xA0" || e.key === "Space" || e.key === " ",
477
- backspace: (e) => e.key === "Backspace",
478
- delete: (e) => e.key === "Delete",
473
+ delete: (e) => e.key === "Delete" || e.key === "Backspace",
479
474
  digit: (e) => /^\d$/.test(e.key),
480
475
  letter: (e) => /^[a-zA-Z]$/.test(e.key),
481
- character: (e) => /^\S$/.test(e.key)
476
+ char: (e) => /^\S$/.test(e.key)
482
477
  };
483
478
  var attr = (el, name, v) => {
484
479
  if (v == null || v === false)
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,r){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,u)=>"symbol"==typeof u?u===o?l:u===a?n:n[u]:"length"===u?c[r]?l.peek():l.value:(r=u,n[u]?n[u].valueOf():u<n.length?(n[u]=e(i(t[u]))).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 u(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?.[a]},s=e(Object.values(t).length);const p=new Proxy(l,{get:(e,t)=>t===o?s:t===a?l:l[t]?.valueOf(),set:(e,t,r,n)=>(n=l[t],u(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]=null,u(l,e,t[e]))}return p}var c={push:1,pop:1,shift:1,unshift:1,splice:1};function u(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 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,a=e(t,(e.parse||g)(s.value,g),r,n);a&&l.push(a)}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 v,m={},g=(e,t,r)=>{if(r=m[e=e.trim()])return r;try{r=v(e)}catch(r){b(r,t,e)}return m[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&&(v=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,c],u)=>{const f=e[j]=document.createTextNode("");e.replaceWith(f);let p,d,y=0;const v=n((()=>{d=null;let e=c(u);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||[]})),m=()=>{r((()=>{let t=0,r=v.value,n=r.length;if(p&&!p[o]){for(let e of p[a]||[])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,o=i({[l]:p[a]?.[n]||p[n],[s]:d?d[n]:n},u),c=(e.content||e).cloneNode(!0),y=e.content?{children:[...c.children],remove(){this.children.map((e=>e.remove()))}}:c;f.before(c),h(y,o),((p[a]||=[])[t]||={})[Symbol.dispose]=()=>{y[Symbol.dispose](),y.remove()}}}y=n}))};let g=0;return t((()=>{v.value[o]?.value,g?g++:(m(),queueMicrotask((()=>(g&&m(),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,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[E]?u:a;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)o.insertBefore(e,c),h(e,l)}}))},d.default=(e,r,l,n)=>{let s,a=n.startsWith("on")&&n.slice(2);return t(a?()=>(s?.(),s=T(e,a,r(l))):()=>{let t=r(l);if(n)P(e,n,L(t,l));else for(let r in t)P(e,K(r),L(t[r],l))})};var T=(e,t,r=(()=>{}))=>{const l=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,l="")=>(r.test=W[t]?.(r,...l.split("-"))||r.test,""))),r}));if(1==l.length)return s(r,l[0]);const n=(t,r=0)=>{let a;return a=s((s=>{r&&a();let o=t.call(e,s);"function"!=typeof o&&(o=()=>{}),r+1<l.length&&n(o,r+1)}),l[r])};return n(r);function s(e,{evt:t,target:r,test:l,defer:n,stop:s,prevent:a,...o}){n&&(e=n(e));const i=n=>{try{l(n)&&(s&&n.stopPropagation(),a&&n.preventDefault(),e.call(r,n))}catch(r){b(r,`:on${t}`,e)}};return r.addEventListener(t,i,o),()=>r.removeEventListener(t,i,o)}},W={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=>_(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=>C.ctrl(e)&&t.every((t=>C[t]?C[t](e):e.key===t)),shift:(e,...t)=>e=>C.shift(e)&&t.every((t=>C[t]?C[t](e):e.key===t)),alt:(e,...t)=>e=>C.alt(e)&&t.every((t=>C[t]?C[t](e):e.key===t)),meta:(e,...t)=>e=>C.meta(e)&&t.every((t=>C[t]?C[t](e):e.key===t)),arrow:()=>C.arrow,enter:()=>C.enter,escape:()=>C.escape,tab:()=>C.tab,space:()=>C.space,backspace:()=>C.backspace,delete:()=>C.delete,digit:()=>C.digit,letter:()=>C.letter,character:()=>C.character},C={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)},P=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},_=(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))},D=(e,t)=>{let r;return l=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(l)}),t)}},K=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase())),L=(e,t)=>e?.replace?e.replace(/\$<([^>]+)>/g,((e,r)=>t[r]??"")):e;d.ref=(e,t,r)=>{r[L(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?L(t,l).split(" ").map((e=>s.add(e))):Array.isArray(t)?t.map((e=>(e=L(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+L(t,l));else{e.setAttribute("style",n);for(let r in t)e.style.setProperty(r,L(t[r],l))}}))},d.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,P(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))))},d.fx=(e,r,l)=>t((()=>r(l))),h.use(S),h.use({compile:e=>h.constructor("__scope",`with (__scope) { return ${e} };`)});var M=h;export{M as default};
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,A,w={};((e,t)=>{for(var r in t)o(e,r,{get:t[r],enumerable:!0})})(w,{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)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=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=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,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,K(t,l));else for(let r in t)W(e,_(r),K(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=>/^[a-zA-Z]$/.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)}},_=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),o=new Set;t&&("string"==typeof t?K(t,l).split(" ").map((e=>o.add(e))):Array.isArray(t)?t.map((e=>(e=K(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+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,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(w),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.3.0",
4
+ "version": "10.4.0",
5
5
  "main": "./sprae.js",
6
6
  "module": "./sprae.js",
7
7
  "type": "module",
package/readme.md CHANGED
@@ -183,7 +183,7 @@ Attach event(s) listener with optional modifiers.
183
183
  <!-- multiple events -->
184
184
  <input :value="text" :oninput:onchange="e => text = e.target.value">
185
185
 
186
- <!-- events sequence -->
186
+ <!-- sequence -->
187
187
  <button :onfocus..onblur="e => ( handleFocus(), e => handleBlur())">
188
188
 
189
189
  <!-- modifiers -->
@@ -193,10 +193,10 @@ Attach event(s) listener with optional modifiers.
193
193
  ##### Modifiers:
194
194
 
195
195
  * `.once`, `.passive`, `.capture` – listener [options](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options).
196
- * `.prevent`, `.stop` – prevent default or stop propagation.
196
+ * `.prevent`, `.stop` + `.immediate` – prevent default or stop propagation.
197
197
  * `.window`, `.document`, `.outside`, `.self` – specify event target.
198
198
  * `.throttle-<ms>`, `.debounce-<ms>` – defer function call with one of the methods.
199
- * `.ctrl`, `.shift`, `.alt`, `.meta`, `.arrow`, `.enter`, `.escape`, `.tab`, `.space`, `.backspace`, `.delete`, `.digit`, `.letter`, `.character` – filter by [`event.key`](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).
199
+ * `.ctrl`, `.shift`, `.alt`, `.meta`, `.enter`, `.esc`, `.tab`, `.space`, `.delete` (+backspace), `.up`, `.right`, `.down`, `.left`, `.arrow` (up/right/down/left), `.digit` (0-9), `.letter` (a-z), `.char` (non-space) – filter by [`event.key`](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).
200
200
  * `.ctrl-<key>, .alt-<key>, .meta-<key>, .shift-<key>` – key combinations, eg. `.ctrl-alt-delete` or `.meta-x`.
201
201
  * `.*` – any other modifier has no effect, but allows binding multiple handlers to same event (like jQuery event classes).
202
202