sprae 10.2.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,47 +2,56 @@ 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
-
20
-
21
- // bind event to a target
22
- const on = (el, e, fn = () => { }) => {
23
- const ctx = { evt: '', target: el, test: () => true };
24
-
25
- // onevt.debounce-108 -> evt.debounce-108
26
- ctx.evt = e.replace(
27
- /\.(\w+)?-?([-\w]+)?/g,
28
- (match, mod, param = "") => ((ctx.test = mods[mod]?.(ctx, ...param.split("-")) || ctx.test), ""),
29
- );
30
-
31
- // add listener applying the context
32
- const { evt, target, test, defer, stop, prevent, ...opts } = ctx;
33
-
34
- if (defer) fn = defer(fn);
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
+ });
12
+
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.
15
+ // ona..onb
16
+ const ctxs = name.split('..').map(e => {
17
+ let ctx = { evt: '', target, test: () => true };
18
+ ctx.evt = (e.startsWith('on') ? e.slice(2) : e).replace(/\.(\w+)?-?([-\w]+)?/g,
19
+ (match, mod, param = '') => (ctx.test = mods[mod]?.(ctx, ...param.split('-')) || ctx.test, '')
20
+ );
21
+ return ctx;
22
+ });
23
+
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]);
33
+ }
34
+
35
+ return effect(() => (
36
+ startFn = evaluate(state),
37
+ !off && nextListener(startFn),
38
+ () => startFn = null // nil startFn to autodispose chain
39
+ ))
40
+
41
+ // add listener with the context
42
+ function addListener(fn, { evt, target, test, defer, stop, prevent, immediate, ...opts }) {
43
+ if (defer) fn = defer(fn)
44
+
45
+ const cb = (e) => {
46
+ try {
47
+ test(e) && (stop && (immediate ? e.stopImmediatePropagation() : e.stopPropagation()), prevent && e.preventDefault(), fn?.(e))
48
+ } catch (error) { err(error, `:on${evt}`, fn) }
49
+ };
35
50
 
36
- const cb = (e) => {
37
- try {
38
- test(e) && (stop && e.stopPropagation(), prevent && e.preventDefault(), fn.call(target, e))
39
- } catch (error) { err(error, `:on${evt}`, fn) }
51
+ target.addEventListener(evt, cb, opts)
52
+ return () => target.removeEventListener(evt, cb, opts)
40
53
  };
41
54
 
42
- target.addEventListener(evt, cb, opts);
43
-
44
- // return off
45
- return () => target.removeEventListener(evt, cb, opts);
46
55
  };
47
56
 
48
57
  // event modifiers
@@ -50,6 +59,7 @@ const mods = {
50
59
  // actions
51
60
  prevent(ctx) { ctx.prevent = true; },
52
61
  stop(ctx) { ctx.stop = true; },
62
+ immediate(ctx) { ctx.immediate = true; },
53
63
 
54
64
  // options
55
65
  once(ctx) { ctx.once = true; },
@@ -79,15 +89,18 @@ const mods = {
79
89
  alt: (_, ...param) => (e) => keys.alt(e) && param.every((p) => (keys[p] ? keys[p](e) : e.key === p)),
80
90
  meta: (_, ...param) => (e) => keys.meta(e) && param.every((p) => (keys[p] ? keys[p](e) : e.key === p)),
81
91
  arrow: () => keys.arrow,
92
+ up: () => keys.up,
93
+ left: () => keys.left,
94
+ right: () => keys.right,
95
+ down: () => keys.down,
82
96
  enter: () => keys.enter,
83
- escape: () => keys.escape,
97
+ esc: () => keys.esc,
84
98
  tab: () => keys.tab,
85
99
  space: () => keys.space,
86
- backspace: () => keys.backspace,
87
100
  delete: () => keys.delete,
88
101
  digit: () => keys.digit,
89
102
  letter: () => keys.letter,
90
- character: () => keys.character,
103
+ char: () => keys.char,
91
104
  };
92
105
 
93
106
  // key testers
@@ -97,15 +110,18 @@ const keys = {
97
110
  alt: (e) => e.altKey || e.key === "Alt",
98
111
  meta: (e) => e.metaKey || e.key === "Meta" || e.key === "Command",
99
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",
100
117
  enter: (e) => e.key === "Enter",
101
- escape: (e) => e.key.startsWith("Esc"),
118
+ esc: (e) => e.key.startsWith("Esc"),
102
119
  tab: (e) => e.key === "Tab",
103
120
  space: (e) => e.key === " " || e.key === "Space" || e.key === " ",
104
- backspace: (e) => e.key === "Backspace",
105
- delete: (e) => e.key === "Delete",
121
+ delete: (e) => e.key === "Delete" || e.key === "Backspace",
106
122
  digit: (e) => /^\d$/.test(e.key),
107
123
  letter: (e) => /^[a-zA-Z]$/.test(e.key),
108
- character: (e) => /^\S$/.test(e.key),
124
+ char: (e) => /^\S$/.test(e.key),
109
125
  };
110
126
 
111
127
  // set attr
package/dist/sprae.js CHANGED
@@ -356,38 +356,45 @@ 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 = (el, e, fn = () => {
373
- }) => {
374
- const ctx = { evt: "", target: el, test: () => true };
375
- ctx.evt = e.replace(
376
- /\.(\w+)?-?([-\w]+)?/g,
377
- (match, mod, param = "") => (ctx.test = mods[mod]?.(ctx, ...param.split("-")) || ctx.test, "")
378
- );
379
- const { evt, target, test, defer, stop, prevent, ...opts } = ctx;
380
- if (defer)
381
- fn = defer(fn);
382
- const cb = (e2) => {
383
- try {
384
- test(e2) && (stop && e2.stopPropagation(), prevent && e2.preventDefault(), fn.call(target, e2));
385
- } catch (error) {
386
- err(error, `:on${evt}`, fn);
387
- }
367
+ attr(target, dashcase(key), ipol(value[key], state));
368
+ });
369
+ const ctxs = name.split("..").map((e) => {
370
+ let ctx = { evt: "", target, test: () => true };
371
+ ctx.evt = (e.startsWith("on") ? e.slice(2) : e).replace(
372
+ /\.(\w+)?-?([-\w]+)?/g,
373
+ (match, mod, param = "") => (ctx.test = mods[mod]?.(ctx, ...param.split("-")) || ctx.test, "")
374
+ );
375
+ return ctx;
376
+ });
377
+ if (ctxs.length == 1)
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]);
388
382
  };
389
- target.addEventListener(evt, cb, opts);
390
- return () => target.removeEventListener(evt, cb, 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 }) {
385
+ if (defer)
386
+ fn = defer(fn);
387
+ const cb = (e) => {
388
+ try {
389
+ test(e) && (stop && (immediate ? e.stopImmediatePropagation() : e.stopPropagation()), prevent && e.preventDefault(), fn?.(e));
390
+ } catch (error) {
391
+ err(error, `:on${evt}`, fn);
392
+ }
393
+ };
394
+ target2.addEventListener(evt, cb, opts);
395
+ return () => target2.removeEventListener(evt, cb, opts);
396
+ }
397
+ ;
391
398
  };
392
399
  var mods = {
393
400
  prevent(ctx) {
@@ -396,6 +403,9 @@ var mods = {
396
403
  stop(ctx) {
397
404
  ctx.stop = true;
398
405
  },
406
+ immediate(ctx) {
407
+ ctx.immediate = true;
408
+ },
399
409
  once(ctx) {
400
410
  ctx.once = true;
401
411
  },
@@ -433,15 +443,18 @@ var mods = {
433
443
  alt: (_, ...param) => (e) => keys.alt(e) && param.every((p) => keys[p] ? keys[p](e) : e.key === p),
434
444
  meta: (_, ...param) => (e) => keys.meta(e) && param.every((p) => keys[p] ? keys[p](e) : e.key === p),
435
445
  arrow: () => keys.arrow,
446
+ up: () => keys.up,
447
+ left: () => keys.left,
448
+ right: () => keys.right,
449
+ down: () => keys.down,
436
450
  enter: () => keys.enter,
437
- escape: () => keys.escape,
451
+ esc: () => keys.esc,
438
452
  tab: () => keys.tab,
439
453
  space: () => keys.space,
440
- backspace: () => keys.backspace,
441
454
  delete: () => keys.delete,
442
455
  digit: () => keys.digit,
443
456
  letter: () => keys.letter,
444
- character: () => keys.character
457
+ char: () => keys.char
445
458
  };
446
459
  var keys = {
447
460
  ctrl: (e) => e.ctrlKey || e.key === "Control" || e.key === "Ctrl",
@@ -449,15 +462,18 @@ var keys = {
449
462
  alt: (e) => e.altKey || e.key === "Alt",
450
463
  meta: (e) => e.metaKey || e.key === "Meta" || e.key === "Command",
451
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",
452
469
  enter: (e) => e.key === "Enter",
453
- escape: (e) => e.key.startsWith("Esc"),
470
+ esc: (e) => e.key.startsWith("Esc"),
454
471
  tab: (e) => e.key === "Tab",
455
472
  space: (e) => e.key === "\xA0" || e.key === "Space" || e.key === " ",
456
- backspace: (e) => e.key === "Backspace",
457
- delete: (e) => e.key === "Delete",
473
+ delete: (e) => e.key === "Delete" || e.key === "Backspace",
458
474
  digit: (e) => /^\d$/.test(e.key),
459
475
  letter: (e) => /^[a-zA-Z]$/.test(e.key),
460
- character: (e) => /^\S$/.test(e.key)
476
+ char: (e) => /^\S$/.test(e.key)
461
477
  };
462
478
  var attr = (el, name, v) => {
463
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)W(e,n,L(t,l));else for(let r in t)W(e,K(r),L(t[r],l))})};var T=(e,t,r=(()=>{}))=>{const l={evt:"",target:e,test:()=>!0};l.evt=t.replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,r="")=>(l.test=C[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=>{try{a(e)&&(i&&e.stopPropagation(),c&&e.preventDefault(),r.call(s,e))}catch(e){b(e,`:on${n}`,r)}};return s.addEventListener(n,f,u),()=>s.removeEventListener(n,f,u)},C={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=>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)},W=(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,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((()=>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.2.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
 
package/store.js CHANGED
@@ -50,7 +50,7 @@ export default function store(values, parent) {
50
50
  return state
51
51
  }
52
52
 
53
- // length mutator methods
53
+ // length changing methods
54
54
  const mut = { push: 1, pop: 1, shift: 1, unshift: 1, splice: 1 }
55
55
 
56
56
  // array store - signals are lazy since arrays can be very large & expensive
@@ -74,8 +74,6 @@ export function list(values) {
74
74
 
75
75
  // console.log('get', key)
76
76
  // if .length is read within .push/etc - peek signal to avoid recursive subscription
77
- // FIXME: is there a better way to maybe to detect writing .length by an array method and ignoring reactions?
78
- // maybe somethign via batching?
79
77
  if (key === 'length') return mut[lastProp] ? _len.peek() : _len.value;
80
78
 
81
79
  lastProp = key;