sprae 9.0.0 → 9.0.1

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
@@ -1,6 +1,6 @@
1
1
  import swapdom from 'swapdom'
2
2
  import * as signals from 'ulive'
3
- import justin from 'subscript/justin.js'
3
+ import justin from 'subscript/justin'
4
4
 
5
5
  // polyfill
6
6
  const _dispose = (Symbol.dispose ||= Symbol("dispose"));
@@ -16,6 +16,7 @@ export const directive = {};
16
16
 
17
17
  // sprae element: apply directives
18
18
  const memo = new WeakMap();
19
+
19
20
  export default function sprae(container, values) {
20
21
  if (!container.children) return // text nodes, comments etc
21
22
 
@@ -23,9 +24,10 @@ export default function sprae(container, values) {
23
24
  if (memo.has(container)) {
24
25
  const [state, effects] = memo.get(container)
25
26
  // we rewrite signals instead of update, because user should have what he provided
26
- // console.log(container, state, values)
27
- for (let k in values) state[k] = values[k]
28
- for (let fx of effects) fx()
27
+ for (let k in values) { state[k] = values[k] }
28
+ // since we call direct updates here, we have to make sure
29
+ // we don't subscribe outer effect, as in case of :each
30
+ untracked(() => { for (let fx of effects) fx() })
29
31
  }
30
32
 
31
33
  // take over existing state instead of creating clone
package/directive/each.js CHANGED
@@ -31,9 +31,7 @@ directive.each = (tpl, expr, state, name) => {
31
31
  // creating via prototype is faster in both creation time & reading time
32
32
  let substate = Object.create(state, { [idxVar]: { value: idx } });
33
33
  substate[itemVar] = item; // can be changed by subsequent updates, need to be writable
34
- item = item.peek?.() ?? item; // unwrap signal
35
- let key = item.key ?? item.id ?? item;
36
- let el;
34
+ let el, key = (item.key ?? item.id ?? item); // NOTE: no need to unwrap singnal, since item fallback covers it
37
35
 
38
36
  if (key == null) el = tpl.cloneNode(true)
39
37
  else {
@@ -44,7 +42,6 @@ directive.each = (tpl, expr, state, name) => {
44
42
  console.warn('Duplicate key', key), el = tpl.cloneNode(true);
45
43
  }
46
44
  else {
47
- console.log(key, count.has(key))
48
45
  count.add(key);
49
46
  el = memo.get(key) || memo.set(key, tpl.cloneNode(true)).get(key);
50
47
  }
package/dist/sprae.js CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
 
7
7
  // node_modules/swapdom/swap-inflate.js
8
8
  var swap = (parent, a, b, end = null) => {
9
- let i = 0, cur2, next, bi, n = b.length, m = a.length, { remove, same, insert, replace } = swap;
9
+ let i = 0, cur2, next2, bi, n = b.length, m = a.length, { remove, same, insert, replace } = swap;
10
10
  while (i < n && i < m && same(a[i], b[i]))
11
11
  i++;
12
12
  while (i < n && i < m && same(b[n - 1], a[m - 1]))
@@ -17,16 +17,16 @@ var swap = (parent, a, b, end = null) => {
17
17
  else {
18
18
  cur2 = a[i];
19
19
  while (i < n) {
20
- bi = b[i++], next = cur2 ? cur2.nextSibling : end;
20
+ bi = b[i++], next2 = cur2 ? cur2.nextSibling : end;
21
21
  if (same(cur2, bi))
22
- cur2 = next;
23
- else if (i < n && same(b[i], next))
24
- replace(cur2, bi, parent), cur2 = next;
22
+ cur2 = next2;
23
+ else if (i < n && same(b[i], next2))
24
+ replace(cur2, bi, parent), cur2 = next2;
25
25
  else
26
26
  insert(cur2, bi, parent);
27
27
  }
28
28
  while (!same(cur2, end))
29
- next = cur2.nextSibling, remove(cur2, parent), cur2 = next;
29
+ next2 = cur2.nextSibling, remove(cur2, parent), cur2 = next2;
30
30
  }
31
31
  return b;
32
32
  };
@@ -123,32 +123,29 @@ var parse = (s) => (idx = 0, cur = s, s = expr(), cur[idx] ? err2() : s || "");
123
123
  var err2 = (msg = "Bad syntax", lines = cur.slice(0, idx).split("\n"), last2 = lines.pop()) => {
124
124
  let before = cur.slice(idx - 108, idx).split("\n").pop();
125
125
  let after = cur.slice(idx, idx + 108).split("\n").shift();
126
- throw EvalError(`${msg} at ${lines.length}:${last2.length} \`${idx >= 108 ? "\u2026" : ""}${before}\u25B6${after}\``, "font-weight: bold");
126
+ throw EvalError(`${msg} at ${lines.length}:${last2.length} \`${idx >= 108 ? "\u2026" : ""}${before}\u2503${after}\``, "font-weight: bold");
127
127
  };
128
- var skip = (is = 1, from = idx, l) => {
129
- if (typeof is == "number")
130
- idx += is;
131
- else
132
- while (l = is(cur.charCodeAt(idx)))
133
- idx += l;
128
+ var next = (is, from = idx, l) => {
129
+ while (l = is(cur.charCodeAt(idx)))
130
+ idx += l;
134
131
  return cur.slice(from, idx);
135
132
  };
133
+ var skip = (n = 1, from = idx) => (idx += n, cur.slice(from, idx));
136
134
  var expr = (prec = 0, end, cc, token2, newNode, fn) => {
137
- while ((cc = parse.space()) && (newNode = ((fn = lookup[cc]) && fn(token2, prec)) ?? (!token2 && parse.id())))
135
+ while ((cc = parse.space()) && (newNode = ((fn = lookup[cc]) && fn(token2, prec)) ?? (!token2 && next(parse.id))))
138
136
  token2 = newNode;
139
137
  if (end)
140
138
  cc == end ? idx++ : err2();
141
139
  return token2;
142
140
  };
143
- var isId = (c) => c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || c == 36 || c == 95 || c >= 192 && c != 215 && c != 247;
144
- var id = parse.id = () => skip(isId);
141
+ var id = parse.id = (c) => c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || c == 36 || c == 95 || c >= 192 && c != 215 && c != 247;
145
142
  var space = parse.space = (cc) => {
146
143
  while ((cc = cur.charCodeAt(idx)) <= SPACE)
147
144
  idx++;
148
145
  return cc;
149
146
  };
150
147
  var lookup = [];
151
- var token = (op, prec = SPACE, map, c = op.charCodeAt(0), l = op.length, prev = lookup[c], word = op.toUpperCase() !== op) => lookup[c] = (a, curPrec, from = idx) => curPrec < prec && (l < 2 || cur.substr(idx, l) == op) && (!word || !isId(cur.charCodeAt(idx + l))) && (idx += l, map(a, curPrec)) || (idx = from, prev?.(a, curPrec));
148
+ var token = (op, prec = SPACE, map, c = op.charCodeAt(0), l = op.length, prev = lookup[c], word = op.toUpperCase() !== op) => lookup[c] = (a, curPrec, from = idx) => curPrec < prec && (l < 2 || cur.substr(idx, l) == op) && (!word || !parse.id(cur.charCodeAt(idx + l))) && (idx += l, map(a, curPrec)) || (idx = from, prev?.(a, curPrec));
152
149
  var binary = (op, prec, right = false) => token(op, prec, (a, b) => a && (b = expr(prec - (right ? 0.5 : 0))) && [op, a, b]);
153
150
  var unary = (op, prec, post) => token(op, prec, (a) => post ? a && [op, a] : !a && (a = expr(prec - 0.5)) && [op, a]);
154
151
  var nary = (op, prec) => {
@@ -171,10 +168,10 @@ var prop = (a, fn, generic, obj, path) => a[0] === "()" ? prop(a[1], fn, generic
171
168
  var compile_default = compile;
172
169
 
173
170
  // node_modules/subscript/feature/number.js
174
- var num = (a) => a ? err2() : [, (a = +skip((c) => c === PERIOD || c >= _0 && c <= _9 || (c === _E || c === _e ? 2 : 0))) != a ? err2() : a];
171
+ var num = (a, _) => [, (a = +next((c) => c === PERIOD || c >= _0 && c <= _9 || (c === _E || c === _e ? 2 : 0))) != a ? err2() : a];
175
172
  lookup[PERIOD] = (a) => !a && num();
176
173
  for (let i = _0; i <= _9; i++)
177
- lookup[i] = num;
174
+ lookup[i] = (a) => a ? err2() : num();
178
175
 
179
176
  // node_modules/subscript/feature/string.js
180
177
  var escape = { n: "\n", r: "\r", t: " ", b: "\b", f: "\f", v: "\v" };
@@ -275,14 +272,14 @@ operator("=", (a, b) => (b = compile(b), prop(a, (container, path, ctx) => conta
275
272
  var subscript_default = (s) => compile_default(parse_default(s));
276
273
 
277
274
  // node_modules/subscript/feature/comment.js
278
- token("/*", PREC_TOKEN, (a, prec) => (skip((c) => c !== STAR && cur.charCodeAt(idx + 1) !== 47), skip(2), a || expr(prec) || []));
279
- token("//", PREC_TOKEN, (a, prec) => (skip((c) => c >= SPACE), a || expr(prec) || [""]));
275
+ token("/*", PREC_TOKEN, (a, prec) => (next((c) => c !== STAR && cur.charCodeAt(idx + 1) !== 47), skip(2), a || expr(prec) || []));
276
+ token("//", PREC_TOKEN, (a, prec) => (next((c) => c >= SPACE), a || expr(prec) || [""]));
280
277
 
281
278
  // node_modules/subscript/feature/pow.js
282
279
  binary("**", PREC_EXP, true), operator("**", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) ** b(ctx)));
283
280
 
284
281
  // node_modules/subscript/feature/ternary.js
285
- token("?", PREC_ASSIGN, (a, b, c) => a && (b = expr(PREC_ASSIGN, COLON)) && (c = expr(PREC_ASSIGN + 1), ["?", a, b, c]));
282
+ token("?", PREC_ASSIGN, (a, b, c) => a && (b = expr(PREC_ASSIGN - 0.5, COLON)) && (c = expr(PREC_ASSIGN - 0.5), ["?", a, b, c]));
286
283
  operator("?", (a, b, c) => (a = compile(a), b = compile(b), c = compile(c), (ctx) => a(ctx) ? b(ctx) : c(ctx)));
287
284
 
288
285
  // node_modules/subscript/feature/bool.js
@@ -291,13 +288,16 @@ token("false", PREC_TOKEN, (a) => a ? err() : [, false]);
291
288
 
292
289
  // node_modules/subscript/feature/array.js
293
290
  group("[]", PREC_TOKEN);
294
- operator("[]", (a, b) => !a ? () => [] : a[0] === "," ? (a = a.slice(1).map(compile), (ctx) => a.map((a2) => a2(ctx))) : (a = compile(a), (ctx) => [a(ctx)]));
291
+ operator(
292
+ "[]",
293
+ (a, b) => (a = !a ? [] : a[0] === "," ? a.slice(1) : [a], a = a.map((a2) => a2[0] === "..." ? (a2 = compile(a2[1]), (ctx) => a2(ctx)) : (a2 = compile(a2), (ctx) => [a2(ctx)])), (ctx) => a.flatMap((a2) => a2(ctx)))
294
+ );
295
295
 
296
296
  // node_modules/subscript/feature/object.js
297
297
  group("{}", PREC_TOKEN);
298
- operator("{}", (a, b) => !a ? () => ({}) : a[0] === "," ? (a = a.slice(1).map(compile), (ctx) => Object.fromEntries(a.map((a2) => a2(ctx)))) : a[0] === ":" ? (a = compile(a), (ctx) => Object.fromEntries([a(ctx)])) : (b = compile(a), (ctx) => ({ [a]: b(ctx) })));
299
- binary(":", PREC_ASSIGN, true);
300
- operator(":", (a, b) => (b = compile(b), a = Array.isArray(a) ? compile(a) : ((a2) => a2).bind(0, a), (ctx) => [a(ctx), b(ctx)]));
298
+ operator("{}", (a, b) => (a = !a ? [] : a[0] !== "," ? [a] : a.slice(1), a = a.map((p) => compile(typeof p === "string" ? [":", p, p] : p)), (ctx) => Object.fromEntries(a.flatMap((frag) => frag(ctx)))));
299
+ binary(":", PREC_ASSIGN - 0.5, true);
300
+ operator(":", (a, b) => (b = compile(b), Array.isArray(a) ? (a = compile(a), (ctx) => [[a(ctx), b(ctx)]]) : (ctx) => [[a, b(ctx)]]));
301
301
 
302
302
  // node_modules/subscript/feature/arrow.js
303
303
  binary("=>", PREC_ASSIGN, true);
@@ -315,11 +315,15 @@ token("?.", PREC_ACCESS, (a, b) => a && (b = expr(PREC_ACCESS), !b?.map) && ["?.
315
315
  operator("?.", (a, b) => b && (a = compile(a), (ctx) => a(ctx)?.[b]));
316
316
  operator("(", (a, b, container, args, path, optional) => a[0] === "?." && (a[2] || Array.isArray(a[1])) && (args = !b ? () => [] : b[0] === "," ? (b = b.slice(1).map(compile), (ctx) => b.map((a2) => a2(ctx))) : (b = compile(b), (ctx) => [b(ctx)]), !a[2] && (optional = true, a = a[1]), a[0] === "[" ? path = compile(a[2]) : path = () => a[2], container = compile(a[1]), optional ? (ctx) => container(ctx)?.[path(ctx)]?.(...args(ctx)) : (ctx) => container(ctx)?.[path(ctx)](...args(ctx))));
317
317
 
318
+ // node_modules/subscript/feature/spread.js
319
+ unary("...", PREC_PREFIX);
320
+ operator("...", (a) => (a = compile(a), (ctx) => Object.entries(a(ctx))));
321
+
318
322
  // node_modules/subscript/justin.js
319
323
  binary("in", PREC_COMP), operator("in", (a, b) => b && (a = compile_default(a), b = compile_default(b), (ctx) => a(ctx) in b(ctx)));
320
324
  binary("===", PREC_EQ), binary("!==", 9);
321
325
  operator("===", (a, b) => (a = compile_default(a), b = compile_default(b), (ctx) => a(ctx) === b(ctx)));
322
- operator("===", (a, b) => (a = compile_default(a), b = compile_default(b), (ctx) => a(ctx) !== b(ctx)));
326
+ operator("!==", (a, b) => (a = compile_default(a), b = compile_default(b), (ctx) => a(ctx) !== b(ctx)));
323
327
  binary("??", PREC_LOR);
324
328
  operator("??", (a, b) => b && (a = compile_default(a), b = compile_default(b), (ctx) => a(ctx) ?? b(ctx)));
325
329
  binary("??=", PREC_ASSIGN, true);
@@ -344,10 +348,13 @@ function sprae(container, values) {
344
348
  return;
345
349
  if (memo.has(container)) {
346
350
  const [state2, effects2] = memo.get(container);
347
- for (let k in values)
351
+ for (let k in values) {
348
352
  state2[k] = values[k];
349
- for (let fx of effects2)
350
- fx();
353
+ }
354
+ untracked2(() => {
355
+ for (let fx of effects2)
356
+ fx();
357
+ });
351
358
  }
352
359
  const state = values || {};
353
360
  const effects = [];
@@ -439,9 +446,7 @@ directive.each = (tpl, expr2, state, name) => {
439
446
  let item = items[idx2];
440
447
  let substate = Object.create(state, { [idxVar]: { value: idx2 } });
441
448
  substate[itemVar] = item;
442
- item = item.peek?.() ?? item;
443
- let key = item.key ?? item.id ?? item;
444
- let el;
449
+ let el, key = item.key ?? item.id ?? item;
445
450
  if (key == null)
446
451
  el = tpl.cloneNode(true);
447
452
  else {
@@ -450,7 +455,6 @@ directive.each = (tpl, expr2, state, name) => {
450
455
  if (count.has(key)) {
451
456
  console.warn("Duplicate key", key), el = tpl.cloneNode(true);
452
457
  } else {
453
- console.log(key, count.has(key));
454
458
  count.add(key);
455
459
  el = memo2.get(key) || memo2.set(key, tpl.cloneNode(true)).get(key);
456
460
  }
@@ -470,24 +474,24 @@ directive.each = (tpl, expr2, state, name) => {
470
474
  // directive/if.js
471
475
  var _prevIf = Symbol("if");
472
476
  directive.if = (ifEl, expr2, state, name) => {
473
- let parent = ifEl.parentNode, next = ifEl.nextElementSibling, holder = document.createTextNode(""), evaluate = compile2(expr2, name), cur2, ifs, elses, none = [];
477
+ let parent = ifEl.parentNode, next2 = ifEl.nextElementSibling, holder = document.createTextNode(""), evaluate = compile2(expr2, name), cur2, ifs, elses, none = [];
474
478
  ifEl.after(holder);
475
479
  if (ifEl.content)
476
480
  cur2 = none, ifEl.remove(), ifs = [...ifEl.content.childNodes];
477
481
  else
478
482
  ifs = cur2 = [ifEl];
479
- if (next?.hasAttribute(":else")) {
480
- next.removeAttribute(":else");
481
- if (next.hasAttribute(":if"))
483
+ if (next2?.hasAttribute(":else")) {
484
+ next2.removeAttribute(":else");
485
+ if (next2.hasAttribute(":if"))
482
486
  elses = none;
483
487
  else
484
- next.remove(), elses = next.content ? [...next.content.childNodes] : [next];
488
+ next2.remove(), elses = next2.content ? [...next2.content.childNodes] : [next2];
485
489
  } else
486
490
  elses = none;
487
491
  return () => {
488
492
  const newEls = evaluate(state)?.valueOf() ? ifs : ifEl[_prevIf] ? none : elses;
489
- if (next)
490
- next[_prevIf] = newEls === ifs;
493
+ if (next2)
494
+ next2[_prevIf] = newEls === ifs;
491
495
  if (cur2 != newEls) {
492
496
  if (cur2[0]?.[_each])
493
497
  cur2 = [cur2[0][_each]];
package/dist/sprae.min.js CHANGED
@@ -1 +1 @@
1
- var e=Object.defineProperty,t=(e,r,a,l=null)=>{let n,s,o,i=0,c=a.length,u=r.length,{remove:p,same:f,insert:d,replace:m}=t;for(;i<c&&i<u&&f(r[i],a[i]);)i++;for(;i<c&&i<u&&f(a[c-1],r[u-1]);)l=a[(--u,--c)];if(i==u)for(;i<c;)d(l,a[i++],e);else{for(n=r[i];i<c;)o=a[i++],s=n?n.nextSibling:l,f(n,o)?n=s:i<c&&f(a[i],s)?(m(n,o,e),n=s):d(n,o,e);for(;!f(n,l);)s=n.nextSibling,p(n,e),n=s}return a};t.same=(e,t)=>e==t,t.replace=(e,t,r)=>r.replaceChild(t,e),t.insert=(e,t,r)=>r.insertBefore(t,e),t.remove=(e,t)=>t.removeChild(e);var r,a=t,l={};((t,r)=>{for(var a in r)e(t,a,{get:r[a],enumerable:!0})})(l,{batch:()=>u,computed:()=>c,current:()=>r,effect:()=>i,signal:()=>o,untracked:()=>p});var n,s,o=(e,t,a=new Set)=>((t={get value(){return r?.deps.push(a.add(r)),e},set value(t){if(t!==e){e=t;for(let e of a)e(t)}},peek:()=>e}).toJSON=t.then=t.toString=t.valueOf=()=>t.value,t),i=(e,t,a,l)=>(l=(a=l=>{t?.call?.(),l=r,r=a;try{t=e()}finally{r=l}}).deps=[],a(),e=>{for(t?.call?.();e=l.pop();)e.delete(a)}),c=(e,t=o(),r,a)=>((r={get value(){return a||=i((()=>t.value=e())),t.value},peek:t.peek}).toJSON=r.then=r.toString=r.valueOf=()=>r.value,r),u=e=>e(),p=(e,t,a)=>(t=r,r=null,a=e(),r=t,a),f=e=>(n=0,s=e,e=v(),s[n]?d():e||""),d=(e="Bad syntax",t=s.slice(0,n).split("\n"),r=t.pop())=>{let a=s.slice(n-108,n).split("\n").pop(),l=s.slice(n,n+108).split("\n").shift();throw EvalError(`${e} at ${t.length}:${r.length} \`${n>=108?"…":""}${a}▶${l}\``,"font-weight: bold")},m=(e=1,t=n,r)=>{if("number"==typeof e)n+=e;else for(;r=e(s.charCodeAt(n));)n+=r;return s.slice(t,n)},v=(e=0,t,r,a,l,s)=>{for(;(r=f.space())&&(l=((s=h[r])&&s(a,e))??(!a&&f.id()));)a=l;return t&&(r==t?n++:d()),a},y=e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e,h=(f.id=()=>m(y),f.space=e=>{for(;(e=s.charCodeAt(n))<=32;)n++;return e},[]),b=(e,t=32,r,a=e.charCodeAt(0),l=e.length,o=h[a],i=e.toUpperCase()!==e)=>h[a]=(a,c,u=n)=>c<t&&(l<2||s.substr(n,l)==e)&&(!i||!y(s.charCodeAt(n+l)))&&(n+=l,r(a,c))||(n=u,o?.(a,c)),g=(e,t,r=!1)=>b(e,t,((a,l)=>a&&(l=v(t-(r?.5:0)))&&[e,a,l])),k=(e,t,r)=>b(e,t,(a=>r?a&&[e,a]:!a&&(a=v(t-.5))&&[e,a])),A=(e,t)=>{b(e,t,((r,a)=>(a=v(t),(!r||r[0]!==e)&&(r=[e,r]),r.push(a),r)))},N=(e,t)=>b(e[0],t,(t=>!t&&[e,v(0,e.charCodeAt(1))])),O=(e,t)=>b(e[0],t,(t=>t&&[e[0],t,v(0,e.charCodeAt(1))])),w=f,C=e=>Array.isArray(e)?e[0]?S[e[0]](...e.slice(1)):()=>e[1]:C.id(e),S=(C.id=e=>t=>t?.[e],{}),x=(e,t,r=S[e])=>S[e]=(...e)=>t(...e)||r&&r(...e),E=(e,t,r,a,l)=>"()"===e[0]?E(e[1],t,r):"string"==typeof e?r=>t(r,e,r):"."===e[0]?(a=C(e[1]),l=e[2],e=>t(a(e),l,e)):"["===e[0]?(a=C(e[1]),l=C(e[2]),e=>t(a(e),l(e),e)):r?(e=C(e),r=>t([e(r)],0,r)):()=>d("Bad left value"),$=C,T=e=>e?d():[,(e=+m((e=>46===e||e>=48&&e<=57||(69===e||101===e?2:0))))!=e?d():e];h[46]=e=>!e&&T();for(let e=48;e<=57;e++)h[e]=T;var W={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},j=e=>(t,r,a="")=>{for(t&&d("Unexpected string"),m();(r=s.charCodeAt(n))-e;)92===r?(m(),r=m(),a+=W[r]||r):a+=m();return m()||d("Bad string"),[,a]};h[34]=j(34),h[39]=j(39),O("()",17),x("(",((e,t,r)=>(r=t?","===t[0]?(t=t.slice(1).map((e=>e?C(e):err())),e=>t.map((t=>t(e)))):(t=C(t),e=>[t(e)]):()=>[],E(e,((e,t,a)=>e[t](...r(a))),!0)))),O("[]",17),x("[",((e,t)=>t?(e=C(e),t=C(t),r=>e(r)[t(r)]):err())),g(".",17),x(".",((e,t)=>(e=C(e),t=t[0]?t:t[1],r=>e(r)[t]))),N("()",17),x("()",(e=>(!e&&d("Empty ()"),C(e))));var L=(...e)=>(e=e.map(C),t=>e.map((e=>e(t))).pop());A(",",1),x(",",L),A(";",1),x(";",L),g("*",12),x("*",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)*t(r)))),g("/",12),x("/",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)/t(r)))),g("%",12),x("%",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)%t(r)))),g("*=",2,!0),x("*=",((e,t)=>(t=C(t),E(e,((e,r,a)=>e[r]*=t(a)))))),g("/=",2,!0),x("/=",((e,t)=>(t=C(t),E(e,((e,r,a)=>e[r]/=t(a)))))),g("%=",2,!0),x("%=",((e,t)=>(t=C(t),E(e,((e,r,a)=>e[r]%=t(a)))))),k("+",14),x("+",((e,t)=>!t&&(e=C(e),t=>+e(t)))),k("-",14),x("-",((e,t)=>!t&&(e=C(e),t=>-e(t)))),g("+",11),x("+",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)+t(r)))),g("-",11),x("-",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)-t(r)))),g("+=",2,!0),x("+=",((e,t)=>(t=C(t),E(e,((e,r,a)=>e[r]+=t(a)))))),g("-=",2,!0),x("-=",((e,t)=>(t=C(t),E(e,((e,r,a)=>e[r]-=t(a)))))),b("++",15,(e=>e?["++-",e]:["++",v(14)])),x("++",(e=>E(e,((e,t,r)=>++e[t])))),x("++-",(e=>E(e,((e,t,r)=>e[t]++)))),b("--",15,(e=>e?["--+",e]:["--",v(14)])),x("--",(e=>E(e,((e,t,r)=>--e[t])))),x("--+",(e=>E(e,((e,t,r)=>e[t]--)))),k("~",14),x("~",((e,t)=>!t&&(e=C(e),t=>~e(t)))),g("|",5),x("|",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)|t(r)))),g("&",7),x("&",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)&t(r)))),g("^",6),x("^",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)^t(r)))),g(">>",10),x(">>",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)>>t(r)))),g("<<",10),x("<<",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)<<t(r)))),g("==",8),x("==",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)==t(r)))),g("!=",8),x("!=",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)!=t(r)))),g(">",9),x(">",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)>t(r)))),g("<",9),x("<",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)<t(r)))),g(">=",9),x(">=",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)>=t(r)))),g("<=",9),x("<=",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)<=t(r)))),k("!",14),x("!",((e,t)=>!t&&(e=C(e),t=>!e(t)))),g("||",3),x("||",((e,t)=>(e=C(e),t=C(t),r=>e(r)||t(r)))),g("&&",4),x("&&",((e,t)=>(e=C(e),t=C(t),r=>e(r)&&t(r)))),g("=",2,!0),x("=",((e,t)=>(t=C(t),E(e,((e,r,a)=>e[r]=t(a)))))),b("/*",20,((e,t)=>(m((e=>42!==e&&47!==s.charCodeAt(n+1))),m(2),e||v(t)||[]))),b("//",20,((e,t)=>(m((e=>e>=32)),e||v(t)||[""]))),g("**",13,!0),x("**",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)**t(r)))),b("?",2,((e,t,r)=>e&&(t=v(2,58))&&["?",e,t,v(3)])),x("?",((e,t,r)=>(e=C(e),t=C(t),r=C(r),a=>e(a)?t(a):r(a)))),b("true",20,(e=>e?err():[,!0])),b("false",20,(e=>e?err():[,!1])),N("[]",20),x("[]",((e,t)=>e?","===e[0]?(e=e.slice(1).map(C),t=>e.map((e=>e(t)))):(e=C(e),t=>[e(t)]):()=>[])),N("{}",20),x("{}",((e,t)=>e?","===e[0]?(e=e.slice(1).map(C),t=>Object.fromEntries(e.map((e=>e(t))))):":"===e[0]?(e=C(e),t=>Object.fromEntries([e(t)])):(t=C(e),r=>({[e]:t(r)})):()=>({}))),g(":",2,!0),x(":",((e,t)=>(t=C(t),e=Array.isArray(e)?C(e):(e=>e).bind(0,e),r=>[e(r),t(r)]))),g("=>",2,!0),x("=>",((e,t)=>(e=(e="()"===e[0]?e[1]:e)?e=","===e[0]?e.slice(1):[e]:[],t=C("{}"===t[0]?t[1]:t),(r=null)=>(r=Object.create(r),(...a)=>(e.map(((e,t)=>r[e]=a[t])),t(r)))))),g(""),b("?.",17,(e=>e&&["?.",e])),x("?.",(e=>(e=C(e),t=>e(t)||(()=>{})))),b("?.",17,((e,t)=>e&&!(t=v(17))?.map&&["?.",e,t])),x("?.",((e,t)=>t&&(e=C(e),r=>e(r)?.[t]))),x("(",((e,t,r,a,l,n)=>"?."===e[0]&&(e[2]||Array.isArray(e[1]))&&(a=t?","===t[0]?(t=t.slice(1).map(C),e=>t.map((t=>t(e)))):(t=C(t),e=>[t(e)]):()=>[],!e[2]&&(e=e[1]),l="["===e[0]?C(e[2]):()=>e[2],r=C(e[1]),e=>r(e)?.[l(e)]?.(...a(e))))),g("in",9),x("in",((e,t)=>t&&(e=$(e),t=$(t),r=>e(r)in t(r)))),g("===",8),g("!==",9),x("===",((e,t)=>(e=$(e),t=$(t),r=>e(r)===t(r)))),x("===",((e,t)=>(e=$(e),t=$(t),r=>e(r)!==t(r)))),g("??",3),x("??",((e,t)=>t&&(e=$(e),t=$(t),r=>e(r)??t(r)))),g("??=",2,!0),x("??=",((e,t)=>(t=$(t),E(e,((e,r,a)=>e[r]??=t(a)))))),g("||=",2,!0),x("||=",((e,t)=>(t=$(t),E(e,((e,r,a)=>e[r]||=t(a)))))),g("&&=",2,!0),x("&&=",((e,t)=>(t=$(t),E(e,((e,r,a)=>e[r]&&=t(a)))))),b("undefined",20,(e=>e?d():[,void 0])),b("NaN",20,(e=>e?d():[,NaN])),b("null",20,(e=>e?d():[,null]));var B=Symbol.dispose||=Symbol("dispose"),{signal:D,effect:K,batch:M,computed:P,untracked:J}=l,R={},U=new WeakMap;function Z(e,t){if(!e.children)return;if(U.has(e)){const[r,a]=U.get(e);for(let e in t)r[e]=t[e];for(let e of a)e()}const r=t||{},a=[],l=(e,t=e.parentNode)=>{if(e.attributes)for(let l=0;l<e.attributes.length;){let n=e.attributes[l];if(":"===n.name[0]){e.removeAttribute(n.name);let l=n.name.slice(1).split(":");for(let t of l){let l=(R[t]||R.default)(e,n.value,r,t);l&&(l[B]=K(l),a.push(l))}if(U.has(e))return;if(e.parentNode!==t)return!1}else l++}for(let t,r=0;t=e.children[r];r++)!1===l(t,e)&&r--};return l(e),U.has(e)||(U.set(e,[r,a]),e.classList?.add("∴"),e[B]=()=>{for(;a.length;)a.pop()[B]();e.classList.remove("∴"),U.delete(e);let t=e.getElementsByClassName("∴");for(;t.length;)t[0][B]?.()}),r}var z={},H=(e,t,r)=>{if(r=z[e=e.trim()])return r;try{r=$(w(e))}catch(r){throw Object.assign(r,{message:`∴ ${r.message}\n\n${t}${e?`="${e}"\n\n`:""}`,expr:e})}return z[e]=r},X=a,_=(e,t)=>e?.replace?e.replace(/\$<([^>]+)>/g,((e,r)=>t[r]?.valueOf?.()??"")):e;Z.use=e=>{e.signal&&(D=e.signal,K=e.effect,P=e.computed,M=e.batch||(e=>e()),J=e.untracked||M),e.swap&&(X=e.swap)};var q=Symbol(":each"),F={};R.each=(e,t,r,a)=>{let[l,n]=t.split(/\s+in\s+/),[s,o="_$"]=l.split(/\s*,\s*/);const i=e[q]=document.createTextNode("");e.replaceWith(i);const c=H(n,a),u=new WeakMap;e.removeAttribute(":key");let p=[];return()=>{let t=c(r)?.valueOf(),a=[];"number"==typeof t&&(t=Array.from({length:t},((e,t)=>t)));const l=new WeakSet;for(let n in t){let i=t[n],c=Object.create(r,{[o]:{value:n}});c[s]=i,i=i.peek?.()??i;let p,f=i.key??i.id??i;null==f?p=e.cloneNode(!0):(Object(f)!==f&&(f=F[f]||=Object(f)),l.has(f)?(console.warn("Duplicate key",f),p=e.cloneNode(!0)):(console.log(f,l.has(f)),l.add(f),p=u.get(f)||u.set(f,e.cloneNode(!0)).get(f))),p.content&&(p=p.content.cloneNode(!0)),Z(p,c),11===p.nodeType?a.push(...p.childNodes):a.push(p)}X(i.parentNode,p,p=a,i)}};var G=Symbol("if");R.if=(e,t,r,a)=>{let l,n,s,o=e.parentNode,i=e.nextElementSibling,c=document.createTextNode(""),u=H(t,a),p=[];return e.after(c),e.content?(l=p,e.remove(),n=[...e.content.childNodes]):n=l=[e],i?.hasAttribute(":else")?(i.removeAttribute(":else"),i.hasAttribute(":if")?s=p:(i.remove(),s=i.content?[...i.content.childNodes]:[i])):s=p,()=>{const t=u(r)?.valueOf()?n:e[G]?p:s;if(i&&(i[G]=t===n),l!=t){l[0]?.[q]&&(l=[l[0][q]]),X(o,l,l=t,c);for(let e of l)Z(e,r)}}},R.ref=(e,t,r)=>{let a;return()=>{a&&delete r[a],r[a=_(t,r)]=e}},R.scope=(e,t,r,a)=>{let l=H(t,a);return()=>{Z(e,{...r,...l(r)?.valueOf?.()||{}})}},R.html=(e,t,r,a)=>{let l=H(t,a)(r);if(!l)return;let n=(l.content||l).cloneNode(!0);e.replaceChildren(n),Z(e,r)},R.text=(e,t,r)=>{let a=H(t,"text");return e.content&&e.replaceWith(e=document.createTextNode("")),()=>{let t=a(r)?.valueOf();e.textContent=null==t?"":t}},R.class=(e,t,r)=>{let a=H(t,"class"),l=new Set;return()=>{let t=a(r),n=new Set;t&&("string"==typeof t?_(t?.valueOf?.(),r).split(" ").map((e=>n.add(e))):Array.isArray(t)?t.map((e=>(e=_(e?.valueOf?.(),r))&&n.add(e))):Object.entries(t).map((([e,t])=>t?.valueOf?.()&&n.add(e))));for(let t of l)n.has(t)?n.delete(t):e.classList.remove(t);for(let t of l=n)e.classList.add(t)}},R.style=(e,t,r)=>{let a=H(t,"style"),l=e.getAttribute("style")||"";return l.endsWith(";")||(l+="; "),()=>{let t=a(r)?.valueOf();if("string"==typeof t)e.setAttribute("style",l+_(t,r));else{e.setAttribute("style",l);for(let a in t)e.style.setProperty(a,_(t[a],r))}}},R.default=(e,t,r,a)=>{let l=a.startsWith("on")&&a.slice(2),n=H(t,a);if(l){let t;return()=>(t?.(),t=I(e,l,n(r)))}return()=>{let t=n(r)?.valueOf();if(a)Y(e,a,_(t,r));else for(let a in t)Y(e,re(a),_(t[a],r))}};var I=(e,t,r=(()=>{}))=>{const a={evt:"",target:e,test:()=>!0};a.evt=t.replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,r="")=>(a.test=Q[t]?.(a,...r.split("-"))||a.test,"")));const{evt:l,target:n,test:s,defer:o,stop:i,prevent:c,...u}=a;o&&(r=o(r));const p=e=>s(e)&&(i&&e.stopPropagation(),c&&e.preventDefault(),r.call(n,e));return n.addEventListener(l,p,u),()=>n.removeEventListener(l,p,u)},Q={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=>ee(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>te(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=>V.ctrl(e)&&t.every((t=>V[t]?V[t](e):e.key===t)),shift:(e,...t)=>e=>V.shift(e)&&t.every((t=>V[t]?V[t](e):e.key===t)),alt:(e,...t)=>e=>V.alt(e)&&t.every((t=>V[t]?V[t](e):e.key===t)),meta:(e,...t)=>e=>V.meta(e)&&t.every((t=>V[t]?V[t](e):e.key===t)),arrow:()=>V.arrow,enter:()=>V.enter,escape:()=>V.escape,tab:()=>V.tab,space:()=>V.space,backspace:()=>V.backspace,delete:()=>V.delete,digit:()=>V.digit,letter:()=>V.letter,character:()=>V.character},V={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)},Y=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},ee=(e,t)=>{let r,a,l=n=>{r=!0,setTimeout((()=>{if(r=!1,a)return a=!1,l(n),e(n)}),t)};return t=>r?a=!0:(l(t),e(t))},te=(e,t)=>{let r;return a=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(a)}),t)}},re=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase()));R.value=(e,t,r)=>{let a,l,n=H(t,"value"),s="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(a=e.selectionStart,l=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),a&&e.setSelectionRange(a,l)):"checkbox"===e.type?t=>(e.checked=t,Y(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()=>s(n(r)?.valueOf?.())},R.fx=(e,t,r,a)=>{let l=H(t,a);return()=>l(r)};export{M as batch,H as compile,P as computed,Z as default,R as directive,K as effect,_ as ipol,D as signal,X as swap,J as untracked};
1
+ var e=Object.defineProperty,t=(e,r,a,l=null)=>{let s,n,o,i=0,c=a.length,u=r.length,{remove:p,same:f,insert:d,replace:v}=t;for(;i<c&&i<u&&f(r[i],a[i]);)i++;for(;i<c&&i<u&&f(a[c-1],r[u-1]);)l=a[(--u,--c)];if(i==u)for(;i<c;)d(l,a[i++],e);else{for(s=r[i];i<c;)o=a[i++],n=s?s.nextSibling:l,f(s,o)?s=n:i<c&&f(a[i],n)?(v(s,o,e),s=n):d(s,o,e);for(;!f(s,l);)n=s.nextSibling,p(s,e),s=n}return a};t.same=(e,t)=>e==t,t.replace=(e,t,r)=>r.replaceChild(t,e),t.insert=(e,t,r)=>r.insertBefore(t,e),t.remove=(e,t)=>t.removeChild(e);var r,a=t,l={};((t,r)=>{for(var a in r)e(t,a,{get:r[a],enumerable:!0})})(l,{batch:()=>u,computed:()=>c,current:()=>r,effect:()=>i,signal:()=>o,untracked:()=>p});var s,n,o=(e,t,a=new Set)=>((t={get value(){return r?.deps.push(a.add(r)),e},set value(t){if(t!==e){e=t;for(let e of a)e(t)}},peek:()=>e}).toJSON=t.then=t.toString=t.valueOf=()=>t.value,t),i=(e,t,a,l)=>(l=(a=l=>{t?.call?.(),l=r,r=a;try{t=e()}finally{r=l}}).deps=[],a(),e=>{for(t?.call?.();e=l.pop();)e.delete(a)}),c=(e,t=o(),r,a)=>((r={get value(){return a||=i((()=>t.value=e())),t.value},peek:t.peek}).toJSON=r.then=r.toString=r.valueOf=()=>r.value,r),u=e=>e(),p=(e,t,a)=>(t=r,r=null,a=e(),r=t,a),f=e=>(s=0,n=e,e=h(),n[s]?d():e||""),d=(e="Bad syntax",t=n.slice(0,s).split("\n"),r=t.pop())=>{let a=n.slice(s-108,s).split("\n").pop(),l=n.slice(s,s+108).split("\n").shift();throw EvalError(`${e} at ${t.length}:${r.length} \`${s>=108?"…":""}${a}┃${l}\``,"font-weight: bold")},v=(e,t=s,r)=>{for(;r=e(n.charCodeAt(s));)s+=r;return n.slice(t,s)},y=(e=1,t=s)=>(s+=e,n.slice(t,s)),h=(e=0,t,r,a,l,n)=>{for(;(r=f.space())&&(l=((n=m[r])&&n(a,e))??(!a&&v(f.id)));)a=l;return t&&(r==t?s++:d()),a},m=(f.id=e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e,f.space=e=>{for(;(e=n.charCodeAt(s))<=32;)s++;return e},[]),g=(e,t=32,r,a=e.charCodeAt(0),l=e.length,o=m[a],i=e.toUpperCase()!==e)=>m[a]=(a,c,u=s)=>c<t&&(l<2||n.substr(s,l)==e)&&(!i||!f.id(n.charCodeAt(s+l)))&&(s+=l,r(a,c))||(s=u,o?.(a,c)),b=(e,t,r=!1)=>g(e,t,((a,l)=>a&&(l=h(t-(r?.5:0)))&&[e,a,l])),k=(e,t,r)=>g(e,t,(a=>r?a&&[e,a]:!a&&(a=h(t-.5))&&[e,a])),A=(e,t)=>{g(e,t,((r,a)=>(a=h(t),(!r||r[0]!==e)&&(r=[e,r]),r.push(a),r)))},N=(e,t)=>g(e[0],t,(t=>!t&&[e,h(0,e.charCodeAt(1))])),O=(e,t)=>g(e[0],t,(t=>t&&[e[0],t,h(0,e.charCodeAt(1))])),w=f,C=e=>Array.isArray(e)?e[0]?S[e[0]](...e.slice(1)):()=>e[1]:C.id(e),S=(C.id=e=>t=>t?.[e],{}),x=(e,t,r=S[e])=>S[e]=(...e)=>t(...e)||r&&r(...e),$=(e,t,r,a,l)=>"()"===e[0]?$(e[1],t,r):"string"==typeof e?r=>t(r,e,r):"."===e[0]?(a=C(e[1]),l=e[2],e=>t(a(e),l,e)):"["===e[0]?(a=C(e[1]),l=C(e[2]),e=>t(a(e),l(e),e)):r?(e=C(e),r=>t([e(r)],0,r)):()=>d("Bad left value"),E=C,T=(e,t)=>[,(e=+v((e=>46===e||e>=48&&e<=57||(69===e||101===e?2:0))))!=e?d():e];m[46]=e=>!e&&T();for(let e=48;e<=57;e++)m[e]=e=>e?d():T();var W={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},j=e=>(t,r,a="")=>{for(t&&d("Unexpected string"),y();(r=n.charCodeAt(s))-e;)92===r?(y(),r=y(),a+=W[r]||r):a+=y();return y()||d("Bad string"),[,a]};m[34]=j(34),m[39]=j(39),O("()",17),x("(",((e,t,r)=>(r=t?","===t[0]?(t=t.slice(1).map((e=>e?C(e):err())),e=>t.map((t=>t(e)))):(t=C(t),e=>[t(e)]):()=>[],$(e,((e,t,a)=>e[t](...r(a))),!0)))),O("[]",17),x("[",((e,t)=>t?(e=C(e),t=C(t),r=>e(r)[t(r)]):err())),b(".",17),x(".",((e,t)=>(e=C(e),t=t[0]?t:t[1],r=>e(r)[t]))),N("()",17),x("()",(e=>(!e&&d("Empty ()"),C(e))));var L=(...e)=>(e=e.map(C),t=>e.map((e=>e(t))).pop());A(",",1),x(",",L),A(";",1),x(";",L),b("*",12),x("*",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)*t(r)))),b("/",12),x("/",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)/t(r)))),b("%",12),x("%",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)%t(r)))),b("*=",2,!0),x("*=",((e,t)=>(t=C(t),$(e,((e,r,a)=>e[r]*=t(a)))))),b("/=",2,!0),x("/=",((e,t)=>(t=C(t),$(e,((e,r,a)=>e[r]/=t(a)))))),b("%=",2,!0),x("%=",((e,t)=>(t=C(t),$(e,((e,r,a)=>e[r]%=t(a)))))),k("+",14),x("+",((e,t)=>!t&&(e=C(e),t=>+e(t)))),k("-",14),x("-",((e,t)=>!t&&(e=C(e),t=>-e(t)))),b("+",11),x("+",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)+t(r)))),b("-",11),x("-",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)-t(r)))),b("+=",2,!0),x("+=",((e,t)=>(t=C(t),$(e,((e,r,a)=>e[r]+=t(a)))))),b("-=",2,!0),x("-=",((e,t)=>(t=C(t),$(e,((e,r,a)=>e[r]-=t(a)))))),g("++",15,(e=>e?["++-",e]:["++",h(14)])),x("++",(e=>$(e,((e,t,r)=>++e[t])))),x("++-",(e=>$(e,((e,t,r)=>e[t]++)))),g("--",15,(e=>e?["--+",e]:["--",h(14)])),x("--",(e=>$(e,((e,t,r)=>--e[t])))),x("--+",(e=>$(e,((e,t,r)=>e[t]--)))),k("~",14),x("~",((e,t)=>!t&&(e=C(e),t=>~e(t)))),b("|",5),x("|",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)|t(r)))),b("&",7),x("&",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)&t(r)))),b("^",6),x("^",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)^t(r)))),b(">>",10),x(">>",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)>>t(r)))),b("<<",10),x("<<",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)<<t(r)))),b("==",8),x("==",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)==t(r)))),b("!=",8),x("!=",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)!=t(r)))),b(">",9),x(">",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)>t(r)))),b("<",9),x("<",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)<t(r)))),b(">=",9),x(">=",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)>=t(r)))),b("<=",9),x("<=",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)<=t(r)))),k("!",14),x("!",((e,t)=>!t&&(e=C(e),t=>!e(t)))),b("||",3),x("||",((e,t)=>(e=C(e),t=C(t),r=>e(r)||t(r)))),b("&&",4),x("&&",((e,t)=>(e=C(e),t=C(t),r=>e(r)&&t(r)))),b("=",2,!0),x("=",((e,t)=>(t=C(t),$(e,((e,r,a)=>e[r]=t(a)))))),g("/*",20,((e,t)=>(v((e=>42!==e&&47!==n.charCodeAt(s+1))),y(2),e||h(t)||[]))),g("//",20,((e,t)=>(v((e=>e>=32)),e||h(t)||[""]))),b("**",13,!0),x("**",((e,t)=>t&&(e=C(e),t=C(t),r=>e(r)**t(r)))),g("?",2,((e,t,r)=>e&&(t=h(1.5,58))&&["?",e,t,h(1.5)])),x("?",((e,t,r)=>(e=C(e),t=C(t),r=C(r),a=>e(a)?t(a):r(a)))),g("true",20,(e=>e?err():[,!0])),g("false",20,(e=>e?err():[,!1])),N("[]",20),x("[]",((e,t)=>(e=(e=e?","===e[0]?e.slice(1):[e]:[]).map((e=>"..."===e[0]?(e=C(e[1]),t=>e(t)):(e=C(e),t=>[e(t)]))),t=>e.flatMap((e=>e(t)))))),N("{}",20),x("{}",((e,t)=>(e=(e=e?","!==e[0]?[e]:e.slice(1):[]).map((e=>C("string"==typeof e?[":",e,e]:e))),t=>Object.fromEntries(e.flatMap((e=>e(t))))))),b(":",1.5,!0),x(":",((e,t)=>(t=C(t),Array.isArray(e)?(e=C(e),r=>[[e(r),t(r)]]):r=>[[e,t(r)]]))),b("=>",2,!0),x("=>",((e,t)=>(e=(e="()"===e[0]?e[1]:e)?e=","===e[0]?e.slice(1):[e]:[],t=C("{}"===t[0]?t[1]:t),(r=null)=>(r=Object.create(r),(...a)=>(e.map(((e,t)=>r[e]=a[t])),t(r)))))),b(""),g("?.",17,(e=>e&&["?.",e])),x("?.",(e=>(e=C(e),t=>e(t)||(()=>{})))),g("?.",17,((e,t)=>e&&!(t=h(17))?.map&&["?.",e,t])),x("?.",((e,t)=>t&&(e=C(e),r=>e(r)?.[t]))),x("(",((e,t,r,a,l,s)=>"?."===e[0]&&(e[2]||Array.isArray(e[1]))&&(a=t?","===t[0]?(t=t.slice(1).map(C),e=>t.map((t=>t(e)))):(t=C(t),e=>[t(e)]):()=>[],!e[2]&&(e=e[1]),l="["===e[0]?C(e[2]):()=>e[2],r=C(e[1]),e=>r(e)?.[l(e)]?.(...a(e))))),k("...",14),x("...",(e=>(e=C(e),t=>Object.entries(e(t))))),b("in",9),x("in",((e,t)=>t&&(e=E(e),t=E(t),r=>e(r)in t(r)))),b("===",8),b("!==",9),x("===",((e,t)=>(e=E(e),t=E(t),r=>e(r)===t(r)))),x("!==",((e,t)=>(e=E(e),t=E(t),r=>e(r)!==t(r)))),b("??",3),x("??",((e,t)=>t&&(e=E(e),t=E(t),r=>e(r)??t(r)))),b("??=",2,!0),x("??=",((e,t)=>(t=E(t),$(e,((e,r,a)=>e[r]??=t(a)))))),b("||=",2,!0),x("||=",((e,t)=>(t=E(t),$(e,((e,r,a)=>e[r]||=t(a)))))),b("&&=",2,!0),x("&&=",((e,t)=>(t=E(t),$(e,((e,r,a)=>e[r]&&=t(a)))))),g("undefined",20,(e=>e?d():[,void 0])),g("NaN",20,(e=>e?d():[,NaN])),g("null",20,(e=>e?d():[,null]));var B=Symbol.dispose||=Symbol("dispose"),{signal:D,effect:M,batch:K,computed:P,untracked:J}=l,R={},U=new WeakMap;function Z(e,t){if(!e.children)return;if(U.has(e)){const[r,a]=U.get(e);for(let e in t)r[e]=t[e];J((()=>{for(let e of a)e()}))}const r=t||{},a=[],l=(e,t=e.parentNode)=>{if(e.attributes)for(let l=0;l<e.attributes.length;){let s=e.attributes[l];if(":"===s.name[0]){e.removeAttribute(s.name);let l=s.name.slice(1).split(":");for(let t of l){let l=(R[t]||R.default)(e,s.value,r,t);l&&(l[B]=M(l),a.push(l))}if(U.has(e))return;if(e.parentNode!==t)return!1}else l++}for(let t,r=0;t=e.children[r];r++)!1===l(t,e)&&r--};return l(e),U.has(e)||(U.set(e,[r,a]),e.classList?.add("∴"),e[B]=()=>{for(;a.length;)a.pop()[B]();e.classList.remove("∴"),U.delete(e);let t=e.getElementsByClassName("∴");for(;t.length;)t[0][B]?.()}),r}var z={},H=(e,t,r)=>{if(r=z[e=e.trim()])return r;try{r=E(w(e))}catch(r){throw Object.assign(r,{message:`∴ ${r.message}\n\n${t}${e?`="${e}"\n\n`:""}`,expr:e})}return z[e]=r},X=a,_=(e,t)=>e?.replace?e.replace(/\$<([^>]+)>/g,((e,r)=>t[r]?.valueOf?.()??"")):e;Z.use=e=>{e.signal&&(D=e.signal,M=e.effect,P=e.computed,K=e.batch||(e=>e()),J=e.untracked||K),e.swap&&(X=e.swap)};var q=Symbol(":each"),F={};R.each=(e,t,r,a)=>{let[l,s]=t.split(/\s+in\s+/),[n,o="_$"]=l.split(/\s*,\s*/);const i=e[q]=document.createTextNode("");e.replaceWith(i);const c=H(s,a),u=new WeakMap;e.removeAttribute(":key");let p=[];return()=>{let t=c(r)?.valueOf(),a=[];"number"==typeof t&&(t=Array.from({length:t},((e,t)=>t)));const l=new WeakSet;for(let s in t){let i=t[s],c=Object.create(r,{[o]:{value:s}});c[n]=i;let p,f=i.key??i.id??i;null==f?p=e.cloneNode(!0):(Object(f)!==f&&(f=F[f]||=Object(f)),l.has(f)?(console.warn("Duplicate key",f),p=e.cloneNode(!0)):(l.add(f),p=u.get(f)||u.set(f,e.cloneNode(!0)).get(f))),p.content&&(p=p.content.cloneNode(!0)),Z(p,c),11===p.nodeType?a.push(...p.childNodes):a.push(p)}X(i.parentNode,p,p=a,i)}};var G=Symbol("if");R.if=(e,t,r,a)=>{let l,s,n,o=e.parentNode,i=e.nextElementSibling,c=document.createTextNode(""),u=H(t,a),p=[];return e.after(c),e.content?(l=p,e.remove(),s=[...e.content.childNodes]):s=l=[e],i?.hasAttribute(":else")?(i.removeAttribute(":else"),i.hasAttribute(":if")?n=p:(i.remove(),n=i.content?[...i.content.childNodes]:[i])):n=p,()=>{const t=u(r)?.valueOf()?s:e[G]?p:n;if(i&&(i[G]=t===s),l!=t){l[0]?.[q]&&(l=[l[0][q]]),X(o,l,l=t,c);for(let e of l)Z(e,r)}}},R.ref=(e,t,r)=>{let a;return()=>{a&&delete r[a],r[a=_(t,r)]=e}},R.scope=(e,t,r,a)=>{let l=H(t,a);return()=>{Z(e,{...r,...l(r)?.valueOf?.()||{}})}},R.html=(e,t,r,a)=>{let l=H(t,a)(r);if(!l)return;let s=(l.content||l).cloneNode(!0);e.replaceChildren(s),Z(e,r)},R.text=(e,t,r)=>{let a=H(t,"text");return e.content&&e.replaceWith(e=document.createTextNode("")),()=>{let t=a(r)?.valueOf();e.textContent=null==t?"":t}},R.class=(e,t,r)=>{let a=H(t,"class"),l=new Set;return()=>{let t=a(r),s=new Set;t&&("string"==typeof t?_(t?.valueOf?.(),r).split(" ").map((e=>s.add(e))):Array.isArray(t)?t.map((e=>(e=_(e?.valueOf?.(),r))&&s.add(e))):Object.entries(t).map((([e,t])=>t?.valueOf?.()&&s.add(e))));for(let t of l)s.has(t)?s.delete(t):e.classList.remove(t);for(let t of l=s)e.classList.add(t)}},R.style=(e,t,r)=>{let a=H(t,"style"),l=e.getAttribute("style")||"";return l.endsWith(";")||(l+="; "),()=>{let t=a(r)?.valueOf();if("string"==typeof t)e.setAttribute("style",l+_(t,r));else{e.setAttribute("style",l);for(let a in t)e.style.setProperty(a,_(t[a],r))}}},R.default=(e,t,r,a)=>{let l=a.startsWith("on")&&a.slice(2),s=H(t,a);if(l){let t;return()=>(t?.(),t=I(e,l,s(r)))}return()=>{let t=s(r)?.valueOf();if(a)Y(e,a,_(t,r));else for(let a in t)Y(e,re(a),_(t[a],r))}};var I=(e,t,r=(()=>{}))=>{const a={evt:"",target:e,test:()=>!0};a.evt=t.replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,r="")=>(a.test=Q[t]?.(a,...r.split("-"))||a.test,"")));const{evt:l,target:s,test:n,defer:o,stop:i,prevent:c,...u}=a;o&&(r=o(r));const p=e=>n(e)&&(i&&e.stopPropagation(),c&&e.preventDefault(),r.call(s,e));return s.addEventListener(l,p,u),()=>s.removeEventListener(l,p,u)},Q={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=>ee(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>te(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=>V.ctrl(e)&&t.every((t=>V[t]?V[t](e):e.key===t)),shift:(e,...t)=>e=>V.shift(e)&&t.every((t=>V[t]?V[t](e):e.key===t)),alt:(e,...t)=>e=>V.alt(e)&&t.every((t=>V[t]?V[t](e):e.key===t)),meta:(e,...t)=>e=>V.meta(e)&&t.every((t=>V[t]?V[t](e):e.key===t)),arrow:()=>V.arrow,enter:()=>V.enter,escape:()=>V.escape,tab:()=>V.tab,space:()=>V.space,backspace:()=>V.backspace,delete:()=>V.delete,digit:()=>V.digit,letter:()=>V.letter,character:()=>V.character},V={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)},Y=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},ee=(e,t)=>{let r,a,l=s=>{r=!0,setTimeout((()=>{if(r=!1,a)return a=!1,l(s),e(s)}),t)};return t=>r?a=!0:(l(t),e(t))},te=(e,t)=>{let r;return a=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(a)}),t)}},re=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase()));R.value=(e,t,r)=>{let a,l,s=H(t,"value"),n="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(a=e.selectionStart,l=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),a&&e.setSelectionRange(a,l)):"checkbox"===e.type?t=>(e.checked=t,Y(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()=>n(s(r)?.valueOf?.())},R.fx=(e,t,r,a)=>{let l=H(t,a);return()=>l(r)};export{K as batch,H as compile,P as computed,Z as default,R as directive,M as effect,_ as ipol,D as signal,X as swap,J as untracked};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sprae",
3
3
  "description": "DOM microhydration.",
4
- "version": "9.0.0",
4
+ "version": "9.0.1",
5
5
  "main": "./sprae.js",
6
6
  "module": "./sprae.js",
7
7
  "type": "module",
@@ -12,7 +12,7 @@
12
12
  "dist"
13
13
  ],
14
14
  "dependencies": {
15
- "subscript": "^8.2.2",
15
+ "subscript": "^8.3.4",
16
16
  "swapdom": "^1.1.1",
17
17
  "ulive": "^1.0.1"
18
18
  },
@@ -32,6 +32,7 @@
32
32
  "test": "node -r ./test/register.cjs test/test.js",
33
33
  "build": "npm run bundle && npm run min",
34
34
  "bundle": "esbuild --bundle ./sprae.js --outdir=dist --format=esm",
35
+ "watch": "esbuild --bundle --watch ./sprae.js --outdir=dist --format=esm",
35
36
  "min": "terser ./dist/sprae.js -o ./dist/sprae.min.js --module -c passes=3 -m"
36
37
  },
37
38
  "repository": {
package/readme.md CHANGED
@@ -29,281 +29,220 @@ Sprae evaluates `:`-directives and evaporates them, attaching state to html.
29
29
 
30
30
  ## Directives
31
31
 
32
- <details>
33
- <summary><strong>:if, :else</strong></summary>
34
-
35
- #### `:if="condition"`, `:else`
36
-
37
- Control flow of elements.
38
-
39
- ```html
40
- <span :if="foo">foo</span>
41
- <span :else :if="bar">bar</span>
42
- <span :else>baz</span>
43
-
44
- <!-- fragment -->
45
- <template :if="foo">
46
- foo <span>bar</span> baz
47
- </template>
48
- ```
49
- </details>
50
-
51
- <details>
52
- <summary><strong>:each</strong></summary>
53
-
54
- #### `:each="item, index in items"`
32
+ #### `:if="condition"`, `:else`
55
33
 
56
- Multiply element. Item is identified either by `item.id` or `item.key`.
34
+ Control flow of elements.
57
35
 
58
- ```html
59
- <ul><li :each="item in items" :text="item"/></ul>
60
-
61
- <!-- cases -->
62
- <li :each="item, idx in list" />
63
- <li :each="val, key in obj" />
64
- <li :each="idx in number" />
65
-
66
- <!-- by condition -->
67
- <li :if="items" :each="item in items" :text="item" />
68
- <li :else>Empty list</li>
69
-
70
- <!-- fragment -->
71
- <template :each="item in items">
72
- <dt :text="item.term"/>
73
- <dd :text="item.definition"/>
74
- </template>
75
-
76
- <!-- prevent FOUC -->
77
- <style>[:each] {visibility: hidden}</style>
78
- ```
79
- </details>
80
-
81
- <details>
82
- <summary><strong>:text</strong></summary>
83
-
84
- #### `:text="value"`
36
+ ```html
37
+ <span :if="foo">foo</span>
38
+ <span :else :if="bar">bar</span>
39
+ <span :else>baz</span>
85
40
 
86
- Set text content of an element.
41
+ <!-- fragment -->
42
+ <template :if="foo">foo <span>bar</span> baz</template>
43
+ ```
87
44
 
88
- ```html
89
- Welcome, <span :text="user.name">Guest</span>.
90
45
 
91
- <!-- fragment -->
92
- Welcome, <template :text="user.name" />.
93
- ```
94
- </details>
46
+ #### `:each="item, index in items"`
95
47
 
96
- <details>
97
- <summary><strong>:class</strong></summary>
48
+ Multiply element. Item is identified either by `item.id`, `item.key` or `item` itself.
98
49
 
99
- #### `:class="value"`
50
+ ```html
51
+ <ul><li :each="item in items" :text="item"/></ul>
100
52
 
101
- Set class value, extends existing `class`.
53
+ <!-- cases -->
54
+ <li :each="item, idx in list" />
55
+ <li :each="val, key in obj" />
56
+ <li :each="idx in number" />
102
57
 
103
- ```html
104
- <!-- string with interpolation -->
105
- <div :class="'foo $<bar>'"></div>
58
+ <!-- by condition -->
59
+ <li :if="items" :each="item in items" :text="item" />
60
+ <li :else>Empty list</li>
106
61
 
107
- <!-- array/object a-la clsx -->
108
- <div :class="[foo && 'foo', {bar: bar}]"></div>
109
- ```
110
- </details>
62
+ <!-- fragment -->
63
+ <template :each="item in items">
64
+ <dt :text="item.term"/>
65
+ <dd :text="item.definition"/>
66
+ </template>
111
67
 
112
- <details>
113
- <summary><strong>:style</strong></summary>
68
+ <!-- prevent FOUC -->
69
+ <style>[:each] {visibility: hidden}</style>
70
+ ```
114
71
 
115
- #### `:style="value"`
72
+ #### `:text="value"`
116
73
 
117
- Set style value, extends existing `style`.
74
+ Set text content of an element.
118
75
 
119
- ```html
120
- <!-- string with interpolation -->
121
- <div :style="'foo: $<bar>'"></div>
76
+ ```html
77
+ Welcome, <span :text="user.name">Guest</span>.
122
78
 
123
- <!-- object -->
124
- <div :style="{foo: 'bar'}"></div>
79
+ <!-- fragment -->
80
+ Welcome, <template :text="user.name" />.
81
+ ```
125
82
 
126
- <!-- CSS variable -->
127
- <div :style="{'--baz': qux}"></div>
128
- ```
129
- </details>
83
+ #### `:class="value"`
130
84
 
131
- <details>
132
- <summary><strong>:value</strong></summary>
85
+ Set class value, extends existing `class`.
133
86
 
134
- #### `:value="value"`
87
+ ```html
88
+ <!-- string with interpolation -->
89
+ <div :class="'foo $<bar>'"></div>
135
90
 
136
- Set value of an input, textarea or select. Takes handle of `checked` and `selected` attributes.
91
+ <!-- array/object a-la clsx -->
92
+ <div :class="[foo && 'foo', {bar: bar}]"></div>
93
+ ```
137
94
 
138
- ```html
139
- <input :value="value" />
140
- <textarea :value="value" />
95
+ #### `:style="value"`
141
96
 
142
- <!-- selects right option -->
143
- <select :value="selected">
144
- <option :each="i in 5" :value="i" :text="i"></option>
145
- </select>
146
- ```
147
- </details>
97
+ Set style value, extends existing `style`.
148
98
 
149
- <details>
150
- <summary><strong>:*</strong></summary>
99
+ ```html
100
+ <!-- string with interpolation -->
101
+ <div :style="'foo: $<bar>'"></div>
151
102
 
152
- #### `:*="value"`, `:="values"`
103
+ <!-- object -->
104
+ <div :style="{foo: 'bar'}"></div>
153
105
 
154
- Set any attribute(s).
106
+ <!-- CSS variable -->
107
+ <div :style="{'--baz': qux}"></div>
108
+ ```
155
109
 
156
- ```html
157
- <label :for="name" :text="name" />
110
+ #### `:value="value"`
158
111
 
159
- <!-- multiple attributes -->
160
- <input :id:name="name" />
112
+ Set value of an input, textarea or select. Takes handle of `checked` and `selected` attributes.
161
113
 
162
- <!-- spread attributes -->
163
- <input :="{ id: name, name, type: 'text', value }" />
164
- ```
165
- </details>
166
-
167
- <details>
168
- <summary><strong>:scope</strong></summary>
114
+ ```html
115
+ <input :value="value" />
116
+ <textarea :value="value" />
169
117
 
170
- #### `:scope="data"`
118
+ <!-- selects right option -->
119
+ <select :value="selected">
120
+ <option :each="i in 5" :value="i" :text="i"></option>
121
+ </select>
122
+ ```
171
123
 
172
- Define or extend data scope for a subtree.
124
+ #### `:*="value"`, `:="values"`
173
125
 
174
- ```html
175
- <x :scope="{ foo: signal('bar') }">
176
- <!-- extends parent scope -->
177
- <y :scope="{ baz: 'qux' }" :text="foo + baz"></y>
178
- </x>
179
- ```
180
- </details>
126
+ Set any attribute(s).
181
127
 
182
- <details>
183
- <summary><strong>:ref</strong></summary>
128
+ ```html
129
+ <label :for="name" :text="name" />
184
130
 
185
- #### `:ref="name"`
131
+ <!-- multiple attributes -->
132
+ <input :id:name="name" />
186
133
 
187
- Expose element to current scope with `name`.
134
+ <!-- spread attributes -->
135
+ <input :="{ id: name, name, type: 'text', value }" />
136
+ ```
188
137
 
189
- ```html
190
- <textarea :ref="text" placeholder="Enter text..."></textarea>
138
+ #### `:scope="data"`
191
139
 
192
- <!-- iterable items -->
193
- <li :each="item in items" :ref="item">
194
- <input :onfocus..onblur=="e => (item.classList.add('editing'), e => item.classList.remove('editing'))"/>
195
- </li>
196
- ```
197
- </details>
140
+ Define or extend data scope for a subtree.
198
141
 
199
- <details>
200
- <summary><strong>:fx</strong></summary>
142
+ ```html
143
+ <x :scope="{ foo: signal('bar') }">
144
+ <!-- extends parent scope -->
145
+ <y :scope="{ baz: 'qux' }" :text="foo + baz"></y>
146
+ </x>
147
+ ```
201
148
 
202
- #### `:fx="values"`
149
+ #### `:ref="name"`
203
150
 
204
- Run effect, not changing any attribute.<br/>Optional cleanup is called in-between effect calls or on disposal.
151
+ Expose element to current scope with `name`.
205
152
 
206
- ```html
207
- <div :fx="a.value ? foo() : bar()" />
153
+ ```html
154
+ <textarea :ref="text" placeholder="Enter text..."></textarea>
208
155
 
209
- <!-- cleanup function -->
210
- <div :fx="id = setInterval(tick, interval), () => clearInterval(tick)" />
211
- ```
212
- </details>
156
+ <!-- iterable items -->
157
+ <li :each="item in items" :ref="item">
158
+ <input :onfocus..onblur=="e => (item.classList.add('editing'), e => item.classList.remove('editing'))"/>
159
+ </li>
160
+ ```
213
161
 
214
- <details>
215
- <summary><strong>:on*</strong></summary>
162
+ #### `:fx="code"`
216
163
 
217
- #### `:on<event>.<mod>="handler"`, `:on<in>..on<out>="handler"`
164
+ Run effect, not changing any attribute.<br/>Optional cleanup is called in-between effect calls or on disposal.
218
165
 
219
- Attach event(s) listener with possible modifiers.
166
+ ```html
167
+ <div :fx="a.value ? foo() : bar()" />
220
168
 
221
- ```html
222
- <input type="checkbox" :onchange="e => isChecked = e.target.value">
169
+ <!-- cleanup function -->
170
+ <div :fx="id = setInterval(tick, interval), () => clearInterval(tick)" />
171
+ ```
223
172
 
224
- <!-- multiple events -->
225
- <input :value="text" :oninput:onchange="e => text = e.target.value">
173
+ #### `:on*="handler"`
226
174
 
227
- <!-- events sequence -->
228
- <button :onfocus..onblur="e => ( handleFocus(), e => handleBlur())">
175
+ Attach event(s) listener with possible modifiers.
229
176
 
230
- <!-- event modifiers -->
231
- <button :onclick.throttle-500="handler">Not too often</button>
232
- ```
177
+ ```html
178
+ <input type="checkbox" :onchange="e => isChecked = e.target.value">
233
179
 
234
- ##### Modifiers:
180
+ <!-- multiple events -->
181
+ <input :value="text" :oninput:onchange="e => text = e.target.value">
235
182
 
236
- * `.once`, `.passive`, `.capture` – listener [options](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options).
237
- * `.prevent`, `.stop` prevent default or stop propagation.
238
- * `.window`, `.document`, `.outside`, `.self` – specify event target.
239
- * `.throttle-<ms>`, `.debounce-<ms>` – defer function call with one of the methods.
240
- * `.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).
241
- * `.ctrl-<key>, .alt-<key>, .meta-<key>, .shift-<key>` – key combinations, eg. `.ctrl-alt-delete` or `.meta-x`.
242
- * `.*` – any other modifier has no effect, but allows binding multiple handlers to same event (like jQuery event classes).
183
+ <!-- events sequence -->
184
+ <button :onfocus..onblur="e => ( handleFocus(), e => handleBlur())">
243
185
 
244
- </details>
186
+ <!-- event modifiers -->
187
+ <button :onclick.throttle-500="handler">Not too often</button>
188
+ ```
245
189
 
190
+ ##### Modifiers:
246
191
 
247
- <details>
248
- <summary><strong>:html</strong> 🔌</summary>
192
+ * `.once`, `.passive`, `.capture` – listener [options](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options).
193
+ * `.prevent`, `.stop` – prevent default or stop propagation.
194
+ * `.window`, `.document`, `.outside`, `.self` – specify event target.
195
+ * `.throttle-<ms>`, `.debounce-<ms>` – defer function call with one of the methods.
196
+ * `.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).
197
+ * `.ctrl-<key>, .alt-<key>, .meta-<key>, .shift-<key>` – key combinations, eg. `.ctrl-alt-delete` or `.meta-x`.
198
+ * `.*` – any other modifier has no effect, but allows binding multiple handlers to same event (like jQuery event classes).
249
199
 
250
- #### `:html="element"`
200
+ #### `:html="element"` 🔌
251
201
 
252
- > Include as `import 'sprae/directive/html'`.
202
+ > Include as `import 'sprae/directive/html'`.
253
203
 
254
- Set html content of an element or instantiate a template.
204
+ Set html content of an element or instantiate a template.
255
205
 
256
- ```html
257
- Hello, <span :html="userElement">Guest</span>.
206
+ ```html
207
+ Hello, <span :html="userElement">Guest</span>.
258
208
 
259
- <!-- fragment -->
260
- Hello, <template :html="user.name">Guest</template>.
209
+ <!-- fragment -->
210
+ Hello, <template :html="user.name">Guest</template>.
261
211
 
262
- <!-- instantiate template -->
263
- <template :ref="tpl"><span :text="foo"></span></template>
264
- <div :html="tpl" :scope="{foo:'bar'}">...inserted here...</div>
265
- ```
266
- </details>
212
+ <!-- instantiate template -->
213
+ <template :ref="tpl"><span :text="foo"></span></template>
214
+ <div :html="tpl" :scope="{foo:'bar'}">...inserted here...</div>
215
+ ```
267
216
 
217
+ #### `:data="values"` 🔌
268
218
 
269
- <details>
270
- <summary><strong>:data</strong> 🔌</summary>
219
+ > Include as `import 'sprae/directive/data'`.
271
220
 
272
- #### `:data="values"`
221
+ Set `data-*` attributes. CamelCase is converted to dash-case.
273
222
 
274
- > Include as `import 'sprae/directive/data'`.
223
+ ```html
224
+ <input :data="{foo: 1, barBaz: true}" />
225
+ <!-- <input data-foo="1" data-bar-baz /> -->
226
+ ```
275
227
 
276
- Set `data-*` attributes. CamelCase is converted to dash-case.
228
+ #### `:aria="values"` 🔌
277
229
 
278
- ```html
279
- <input :data="{foo: 1, barBaz: true}" />
280
- <!-- <input data-foo="1" data-bar-baz /> -->
281
- ```
282
- </details>
230
+ > Include as `import 'sprae/directive/aria'`.
283
231
 
232
+ Set `aria-*` attributes. Boolean values are stringified.
284
233
 
285
- <details>
286
- <summary><strong>:aria</strong> 🔌</summary>
287
-
288
- #### `:aria="values"`
289
-
290
- > Include as `import 'sprae/directive/aria'`.
291
-
292
- Set `aria-*` attributes. Boolean values are stringified.
293
-
294
- ```html
295
- <input role="combobox" :aria="{
296
- controls: 'joketypes',
297
- autocomplete: 'list',
298
- expanded: false,
299
- activeOption: 'item1',
300
- activedescendant: ''
301
- }" />
302
- <!--
303
- <input role="combobox" aria-controls="joketypes" aria-autocomplete="list" aria-expanded="false" aria-active-option="item1" aria-activedescendant>
304
- -->
305
- ```
306
- </details>
234
+ ```html
235
+ <input role="combobox" :aria="{
236
+ controls: 'joketypes',
237
+ autocomplete: 'list',
238
+ expanded: false,
239
+ activeOption: 'item1',
240
+ activedescendant: ''
241
+ }" />
242
+ <!--
243
+ <input role="combobox" aria-controls="joketypes" aria-autocomplete="list" aria-expanded="false" aria-active-option="item1" aria-activedescendant>
244
+ -->
245
+ ```
307
246
 
308
247
  <!--
309
248
  #### `:onvisible..oninvisible="e => e => {}"`
@@ -426,9 +365,9 @@ To destroy state and detach sprae handlers, call `element[Symbol.dispose]()`. --
426
365
 
427
366
  ## Justification
428
367
 
429
- [Template-parts](https://github.com/dy/template-parts) / [templize](https://github.com/dy/templize) is progressive, but 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). [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) (no access to data, own reactivity, own expressions, own domdiffer).
368
+ [Template-parts](https://github.com/dy/template-parts) / [templize](https://github.com/dy/templize) is progressive, but 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). [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).
430
369
 
431
- _Sprae_ holds to open & minimalistic philosophy, combining _`:`-directives_ with _signals_.
370
+ _Sprae_ holds open & minimalistic philosophy, combining _`:`-directives_ with _signals_.
432
371
 
433
372
  <!--
434
373
  | | [AlpineJS](https://github.com/alpinejs/alpine) | [Petite-Vue](https://github.com/vuejs/petite-vue) | Sprae |
@@ -474,18 +413,15 @@ npm ci
474
413
  npm run build-prod
475
414
 
476
415
  # bench
477
- cd ../../..
478
- cd webdriver-ts
416
+ cd ../../../webdriver-ts
479
417
  npm ci
480
418
  npm run compile
481
419
  npm run bench keyed/sprae
482
420
 
483
421
  # show results
484
- cd ..
485
- cd webdriver-ts-results
422
+ cd ../webdriver-ts-results
486
423
  npm ci
487
- cd ..
488
- cd webdriver-ts
424
+ cd ../webdriver-ts
489
425
  npm run results
490
426
  ```
491
427
  </details>