sprae 11.0.7 → 11.1.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.
package/dist/sprae.umd.js CHANGED
@@ -25,10 +25,10 @@ function use(s) {
25
25
  signal = s.signal;
26
26
  effect = s.effect;
27
27
  computed = s.computed;
28
- batch = s.batch || ((fn) => fn());
28
+ batch = s.batch || batch;
29
29
  untracked = s.untracked || batch;
30
30
  }
31
- var current, batched, signal, effect, computed, batch, untracked;
31
+ var current, signal, effect, computed, batch, untracked;
32
32
  var init_signal = __esm({
33
33
  "signal.js"() {
34
34
  signal = (v, s, obs = /* @__PURE__ */ new Set()) => (s = {
@@ -39,7 +39,7 @@ var init_signal = __esm({
39
39
  set value(val) {
40
40
  if (val === v) return;
41
41
  v = val;
42
- for (let sub of obs) batched ? batched.add(sub) : sub();
42
+ for (let sub of obs) sub();
43
43
  },
44
44
  peek() {
45
45
  return v;
@@ -64,20 +64,8 @@ var init_signal = __esm({
64
64
  },
65
65
  peek: s.peek
66
66
  }, c.toJSON = c.then = c.toString = c.valueOf = () => c.value, c);
67
- batch = (fn) => {
68
- let fxs = batched;
69
- if (!fxs) batched = /* @__PURE__ */ new Set();
70
- try {
71
- fn();
72
- } finally {
73
- if (!fxs) {
74
- fxs = batched;
75
- batched = null;
76
- for (const fx of fxs) fx();
77
- }
78
- }
79
- };
80
- untracked = (fn, prev, v) => (prev = current, current = null, v = fn(), current = prev, v);
67
+ batch = (fn) => fn();
68
+ untracked = batch;
81
69
  }
82
70
  });
83
71
 
@@ -144,14 +132,13 @@ function set(signals, key, v) {
144
132
  else if (s._set) s._set(v);
145
133
  else if (Array.isArray(v) && Array.isArray(s.peek())) {
146
134
  const cur = s.peek();
147
- if (cur[_change]) untracked(() => {
135
+ if (cur[_change]) {
148
136
  batch(() => {
149
137
  let i = 0, l = v.length;
150
138
  for (; i < l; i++) cur[i] = v[i];
151
139
  cur.length = l;
152
140
  });
153
- });
154
- else {
141
+ } else {
155
142
  s.value = v;
156
143
  }
157
144
  } else {
@@ -169,7 +156,7 @@ var init_store = __esm({
169
156
  "store.js"() {
170
157
  init_signal();
171
158
  _signals = Symbol("signals");
172
- _change = Symbol("length");
159
+ _change = Symbol("change");
173
160
  mut = { push: 1, pop: 1, shift: 1, unshift: 1, splice: 1 };
174
161
  }
175
162
  });
@@ -194,13 +181,12 @@ function sprae(el, values) {
194
181
  function init(el2) {
195
182
  if (!el2.childNodes) return;
196
183
  for (let i = 0; i < el2.attributes?.length; ) {
197
- let attr2 = el2.attributes[i];
184
+ let attr2 = el2.attributes[i], update;
198
185
  if (attr2.name[0] === ":") {
199
186
  el2.removeAttribute(attr2.name);
200
187
  for (let name of attr2.name.slice(1).split(":")) {
201
- let dir = directive[name] || directive.default, update = dir(el2, (dir.parse || parse)(attr2.value), state, name);
202
- fx.push(update);
203
- offs.push(effect(update));
188
+ update = (directive[name] || directive.default)(el2, attr2.value, state, name);
189
+ fx.push(update), offs.push(effect(update));
204
190
  if (_state in el2) return;
205
191
  }
206
192
  } else i++;
@@ -209,7 +195,7 @@ function sprae(el, values) {
209
195
  }
210
196
  ;
211
197
  }
212
- var _dispose, _state, _on, _off, directive, memo, parse, err, compile, frag;
198
+ var _dispose, _state, _on, _off, directive, dir, memo, parse, err, compile, frag;
213
199
  var init_core = __esm({
214
200
  "core.js"() {
215
201
  init_signal();
@@ -219,20 +205,22 @@ var init_core = __esm({
219
205
  _on = Symbol("on");
220
206
  _off = Symbol("off");
221
207
  directive = {};
208
+ dir = (name, create, p = parse) => directive[name] = (el, expr, state, name2, update, evaluate) => (evaluate = p(expr), update = create(el, state, expr, name2, evaluate), () => update(evaluate(state)));
222
209
  memo = {};
223
- parse = (expr, dir, fn) => {
210
+ parse = (expr, dir2) => {
211
+ let fn;
224
212
  if (fn = memo[expr = expr.trim()]) return fn;
225
213
  try {
226
214
  fn = compile(expr);
227
215
  } catch (e) {
228
- err(e, dir, expr);
216
+ err(e, dir2, expr);
229
217
  }
230
218
  return memo[expr] = fn;
231
219
  };
232
- err = (e, dir, expr = "") => {
220
+ err = (e, dir2, expr = "") => {
233
221
  throw Object.assign(e, { message: `\u2234 ${e.message}
234
222
 
235
- ${dir}${expr ? `="${expr}"
223
+ ${dir2 || ""}${expr ? `="${expr}"
236
224
 
237
225
  ` : ""}`, expr });
238
226
  };
@@ -270,8 +258,9 @@ var init_if = __esm({
270
258
  "directive/if.js"() {
271
259
  init_core();
272
260
  _prevIf = Symbol("if");
273
- directive.if = (el, evaluate, state) => {
274
- let next = el.nextElementSibling, holder = document.createTextNode(""), curEl, ifEl, elseEl;
261
+ dir("if", (el, state) => {
262
+ const holder = document.createTextNode("");
263
+ let next = el.nextElementSibling, curEl, ifEl, elseEl;
275
264
  el.replaceWith(holder);
276
265
  ifEl = el.content ? frag(el) : el;
277
266
  ifEl[_state] = null;
@@ -279,8 +268,8 @@ var init_if = __esm({
279
268
  next.removeAttribute(":else");
280
269
  if (!next.hasAttribute(":if")) next.remove(), elseEl = next.content ? frag(next) : next, elseEl[_state] = null;
281
270
  }
282
- return () => {
283
- const newEl = evaluate(state) ? ifEl : el[_prevIf] ? null : elseEl;
271
+ return (value) => {
272
+ const newEl = value ? ifEl : el[_prevIf] ? null : elseEl;
284
273
  if (next) next[_prevIf] = newEl === ifEl;
285
274
  if (curEl != newEl) {
286
275
  if (curEl) curEl.remove(), curEl[_off]?.();
@@ -291,7 +280,7 @@ var init_if = __esm({
291
280
  }
292
281
  }
293
282
  };
294
- };
283
+ });
295
284
  }
296
285
  });
297
286
 
@@ -301,38 +290,25 @@ var init_each = __esm({
301
290
  init_core();
302
291
  init_store();
303
292
  init_signal();
304
- directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
305
- const holder = document.createTextNode("");
306
- tpl.replaceWith(holder);
307
- tpl[_state] = null;
308
- let cur, keys2, prevl = 0;
309
- const items = computed(() => {
310
- keys2 = null;
311
- let items2 = evaluate(state);
312
- if (typeof items2 === "number") items2 = Array.from({ length: items2 }, (_, i) => i + 1);
313
- if (items2?.constructor === Object) keys2 = Object.keys(items2), items2 = Object.values(items2);
314
- return items2 || [];
315
- });
316
- const update = () => {
317
- untracked(() => {
293
+ dir(
294
+ "each",
295
+ (tpl, state, expr) => {
296
+ const [itemVar, idxVar = "$"] = expr.split(/\s+in\s+/)[0].split(/\s*,\s*/);
297
+ const holder = document.createTextNode("");
298
+ tpl.replaceWith(holder);
299
+ tpl[_state] = null;
300
+ let cur, keys2, items, prevl = 0;
301
+ const update = () => {
318
302
  var _a, _b;
319
- let i = 0, newItems = items.value, newl = newItems.length;
303
+ let i = 0, newItems = items, newl = newItems.length;
320
304
  if (cur && !cur[_change]) {
321
- for (let s of cur[_signals] || []) {
322
- s[Symbol.dispose]();
323
- }
305
+ for (let s of cur[_signals] || []) s[Symbol.dispose]();
324
306
  cur = null, prevl = 0;
325
307
  }
326
- if (newl < prevl) {
327
- cur.length = newl;
328
- } else {
329
- if (!cur) {
330
- cur = newItems;
331
- } else {
332
- for (; i < prevl; i++) {
333
- cur[i] = newItems[i];
334
- }
335
- }
308
+ if (newl < prevl) cur.length = newl;
309
+ else {
310
+ if (!cur) cur = newItems;
311
+ else while (i < prevl) cur[i] = newItems[i++];
336
312
  for (; i < newl; i++) {
337
313
  cur[i] = newItems[i];
338
314
  let idx = i, scope = store({
@@ -347,127 +323,44 @@ var init_each = __esm({
347
323
  }
348
324
  }
349
325
  prevl = newl;
350
- });
351
- };
352
- let planned = 0;
353
- return () => {
354
- items.value[_change]?.value;
355
- if (!planned++) update(), queueMicrotask(() => (planned > 1 && update(), planned = 0));
356
- };
357
- };
358
- directive.each.parse = (expr) => {
359
- let [leftSide, itemsExpr] = expr.split(/\s+in\s+/);
360
- let [itemVar, idxVar = "$"] = leftSide.split(/\s*,\s*/);
361
- return [itemVar, idxVar, parse(itemsExpr)];
362
- };
363
- }
364
- });
365
-
366
- // directive/ref.js
367
- var init_ref = __esm({
368
- "directive/ref.js"() {
369
- init_core();
370
- directive.ref = (el, evaluate, state) => {
371
- return () => evaluate(state)?.call?.(null, el);
372
- };
373
- }
374
- });
375
-
376
- // directive/with.js
377
- var init_with = __esm({
378
- "directive/with.js"() {
379
- init_core();
380
- init_store();
381
- directive.with = (el, evaluate, rootState) => {
382
- let state;
383
- return () => {
384
- let values = evaluate(rootState);
385
- sprae(el, state ? values : state = store(values, rootState));
386
- };
387
- };
388
- }
389
- });
390
-
391
- // directive/text.js
392
- var init_text = __esm({
393
- "directive/text.js"() {
394
- init_core();
395
- directive.text = (el, evaluate, state) => {
396
- if (el.content) el.replaceWith(el = frag(el).childNodes[0]);
397
- return () => {
398
- let value = evaluate(state);
399
- el.textContent = value == null ? "" : value;
400
- };
401
- };
402
- }
403
- });
404
-
405
- // directive/class.js
406
- var init_class = __esm({
407
- "directive/class.js"() {
408
- init_core();
409
- directive.class = (el, evaluate, state) => {
410
- let cur = /* @__PURE__ */ new Set();
411
- return () => {
412
- let v = evaluate(state);
413
- let clsx = /* @__PURE__ */ new Set();
414
- if (v) {
415
- if (typeof v === "string") v.split(" ").map((cls) => clsx.add(cls));
416
- else if (Array.isArray(v)) v.map((v2) => v2 && clsx.add(v2));
417
- else Object.entries(v).map(([k, v2]) => v2 && clsx.add(k));
418
- }
419
- for (let cls of cur) if (clsx.has(cls)) clsx.delete(cls);
420
- else el.classList.remove(cls);
421
- for (let cls of cur = clsx) el.classList.add(cls);
422
- };
423
- };
424
- }
425
- });
426
-
427
- // directive/style.js
428
- var init_style = __esm({
429
- "directive/style.js"() {
430
- init_core();
431
- directive.style = (el, evaluate, state) => {
432
- let initStyle = el.getAttribute("style");
433
- return () => {
434
- let v = evaluate(state);
435
- if (typeof v === "string") el.setAttribute("style", initStyle + (initStyle.endsWith(";") ? "" : "; ") + v);
436
- else {
437
- if (initStyle) el.setAttribute("style", initStyle);
438
- for (let k in v) k[0] == "-" ? el.style.setProperty(k, v[k]) : el.style[k] = v[k];
439
- }
440
- };
441
- };
326
+ };
327
+ return (value) => {
328
+ keys2 = null;
329
+ if (typeof value === "number") items = Array.from({ length: value }, (_, i) => i + 1);
330
+ else if (value?.constructor === Object) keys2 = Object.keys(value), items = Object.values(value);
331
+ else items = value || [];
332
+ let planned = 0;
333
+ return effect(() => {
334
+ items[_change]?.value;
335
+ if (!planned++) update(), queueMicrotask(() => (planned > 1 && update(), planned = 0));
336
+ });
337
+ };
338
+ },
339
+ // redefine evaluator to take second part of expression
340
+ (expr) => parse(expr.split(/\s+in\s+/)[1])
341
+ );
442
342
  }
443
343
  });
444
344
 
445
345
  // directive/default.js
446
- var mods, keys, attr, throttle, debounce, dashcase;
346
+ var mods, keys, throttle, debounce, attr, dashcase;
447
347
  var init_default = __esm({
448
348
  "directive/default.js"() {
449
349
  init_core();
450
- directive.default = (target, evaluate, state, name) => {
451
- if (!name.startsWith("on")) return () => {
452
- let value = evaluate(state);
453
- if (name) attr(target, name, value);
454
- else for (let key in value) attr(target, dashcase(key), value[key]);
455
- };
350
+ dir("default", (target, state, expr, name) => {
351
+ if (!name.startsWith("on"))
352
+ return name ? (value) => attr(target, name, value) : (value) => {
353
+ for (let key in value) attr(target, dashcase(key), value[key]);
354
+ };
456
355
  const ctxs = name.split("..").map((e) => {
457
356
  let ctx = { evt: "", target, test: () => true };
458
357
  ctx.evt = (e.startsWith("on") ? e.slice(2) : e).replace(
459
358
  /\.(\w+)?-?([-\w]+)?/g,
460
- (match, mod, param = "") => (ctx.test = mods[mod]?.(ctx, ...param.split("-")) || ctx.test, "")
359
+ (_, mod, param = "") => (ctx.test = mods[mod]?.(ctx, ...param.split("-")) || ctx.test, "")
461
360
  );
462
361
  return ctx;
463
362
  });
464
- if (ctxs.length == 1) return () => addListener(evaluate(state), ctxs[0]);
465
- let startFn, nextFn, off, idx = 0;
466
- const nextListener = (fn) => {
467
- off = addListener((e) => (off(), nextFn = fn?.(e), (idx = ++idx % ctxs.length) ? nextListener(nextFn) : startFn && nextListener(startFn)), ctxs[idx]);
468
- };
469
- return () => (startFn = evaluate(state), !off && nextListener(startFn), () => startFn = null);
470
- function addListener(fn, { evt, target: target2, test, defer, stop, prevent, immediate, ...opts }) {
363
+ const addListener = (fn, { evt, target: target2, test, defer, stop, prevent, immediate, ...opts }) => {
471
364
  if (defer) fn = defer(fn);
472
365
  const cb = (e) => {
473
366
  try {
@@ -478,9 +371,14 @@ var init_default = __esm({
478
371
  };
479
372
  target2.addEventListener(evt, cb, opts);
480
373
  return () => target2.removeEventListener(evt, cb, opts);
481
- }
482
- ;
483
- };
374
+ };
375
+ if (ctxs.length == 1) return (v) => addListener(v, ctxs[0]);
376
+ let startFn, nextFn, off, idx = 0;
377
+ const nextListener = (fn) => {
378
+ off = addListener((e) => (off(), nextFn = fn?.(e), (idx = ++idx % ctxs.length) ? nextListener(nextFn) : startFn && nextListener(startFn)), ctxs[idx]);
379
+ };
380
+ return (value) => (startFn = value, !off && nextListener(startFn), () => startFn = null);
381
+ });
484
382
  mods = {
485
383
  // actions
486
384
  prevent(ctx) {
@@ -558,10 +456,6 @@ var init_default = __esm({
558
456
  letter: (e) => /^\p{L}$/gu.test(e.key),
559
457
  char: (e) => /^\S$/.test(e.key)
560
458
  };
561
- attr = (el, name, v) => {
562
- if (v == null || v === false) el.removeAttribute(name);
563
- else el.setAttribute(name, v === true ? "" : typeof v === "number" || typeof v === "string" ? v : "");
564
- };
565
459
  throttle = (fn, limit) => {
566
460
  let pause, planned, block = (e) => {
567
461
  pause = true;
@@ -586,6 +480,10 @@ var init_default = __esm({
586
480
  }, wait);
587
481
  };
588
482
  };
483
+ attr = (el, name, v) => {
484
+ if (v == null || v === false) el.removeAttribute(name);
485
+ else el.setAttribute(name, v === true ? "" : typeof v === "number" || typeof v === "string" ? v : "");
486
+ };
589
487
  dashcase = (str) => {
590
488
  return str.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g, (match, i) => (i ? "-" : "") + match.toLowerCase());
591
489
  };
@@ -593,12 +491,13 @@ var init_default = __esm({
593
491
  });
594
492
 
595
493
  // directive/value.js
494
+ var setter, ensure;
596
495
  var init_value = __esm({
597
496
  "directive/value.js"() {
598
497
  init_core();
599
498
  init_core();
600
499
  init_default();
601
- directive.value = (el, [getValue, setValue], state) => {
500
+ dir("value", (el, state, expr) => {
602
501
  const update = el.type === "text" || el.type === "" ? (value) => el.setAttribute("value", el.value = value == null ? "" : value) : el.tagName === "TEXTAREA" || el.type === "text" || el.type === "" ? (value, from, to) => (
603
502
  // we retain selection in input
604
503
  (from = el.selectionStart, to = el.selectionEnd, el.setAttribute("value", el.value = value == null ? "" : value), from && el.setSelectionRange(from, to))
@@ -610,39 +509,102 @@ var init_value = __esm({
610
509
  for (let o of el.options) o.removeAttribute("selected");
611
510
  for (let v of value) el.querySelector(`[value="${v}"]`).setAttribute("selected", "");
612
511
  } : (value) => el.value = value;
613
- const handleChange = el.type === "checkbox" ? () => setValue(state, el.checked) : el.type === "select-multiple" ? () => setValue(state, [...el.selectedOptions].map((o) => o.value)) : (e) => setValue(state, el.selectedIndex < 0 ? null : el.value);
614
- el.oninput = el.onchange = handleChange;
615
- if (el.type?.startsWith("select")) {
616
- new MutationObserver(handleChange).observe(el, { childList: true, subtree: true, attributes: true });
617
- sprae(el, state);
618
- }
619
- return () => {
620
- update(getValue(state));
621
- };
622
- };
623
- directive.value.parse = (expr) => {
624
- let evaluate = [parse(expr)];
512
+ ensure(state, expr);
625
513
  try {
626
- const set2 = parse(`${expr}=__`);
627
- evaluate.push((state, value) => {
628
- state.__ = value;
629
- set2(state, value);
630
- delete state.__;
631
- });
632
- } catch (e) {
514
+ const set2 = setter(expr);
515
+ const handleChange = el.type === "checkbox" ? () => set2(state, el.checked) : el.type === "select-multiple" ? () => set2(state, [...el.selectedOptions].map((o) => o.value)) : () => set2(state, el.selectedIndex < 0 ? null : el.value);
516
+ el.oninput = el.onchange = handleChange;
517
+ if (el.type?.startsWith("select")) {
518
+ new MutationObserver(handleChange).observe(el, { childList: true, subtree: true, attributes: true });
519
+ sprae(el, state);
520
+ }
521
+ } catch {
633
522
  }
634
- return evaluate;
523
+ return update;
524
+ });
525
+ setter = (expr, set2 = parse(`${expr}=__`)) => (
526
+ // FIXME: if there's a simpler way to set value in justin?
527
+ (state, value) => (state.__ = value, set2(state, value), delete state.__)
528
+ );
529
+ ensure = (state, expr, name = expr.match(/^\w+(?=\s*(?:\.|\[|$))/)) => {
530
+ var _a;
531
+ return name && (state[_a = name[0]] || (state[_a] = null));
635
532
  };
636
533
  }
637
534
  });
638
535
 
536
+ // directive/ref.js
537
+ var init_ref = __esm({
538
+ "directive/ref.js"() {
539
+ init_core();
540
+ init_value();
541
+ dir("ref", (el, state, expr, _, ev) => (ensure(state, expr), ev(state) == null ? (setter(expr)(state, el), (_2) => _2) : (v) => v.call(null, el)));
542
+ }
543
+ });
544
+
545
+ // directive/with.js
546
+ var init_with = __esm({
547
+ "directive/with.js"() {
548
+ init_core();
549
+ init_store();
550
+ dir("with", (el, rootState, state) => (state = null, (values) => sprae(el, state ? values : state = store(values, rootState))));
551
+ }
552
+ });
553
+
554
+ // directive/text.js
555
+ var init_text = __esm({
556
+ "directive/text.js"() {
557
+ init_core();
558
+ dir("text", (el) => (
559
+ // <template :text="a"/> or previously initialized template
560
+ (el.content && el.replaceWith(el = frag(el).childNodes[0]), (value) => el.textContent = value == null ? "" : value)
561
+ ));
562
+ }
563
+ });
564
+
565
+ // directive/class.js
566
+ var init_class = __esm({
567
+ "directive/class.js"() {
568
+ init_core();
569
+ dir(
570
+ "class",
571
+ (el, cur) => (cur = /* @__PURE__ */ new Set(), (v) => {
572
+ let clsx = /* @__PURE__ */ new Set();
573
+ if (v) {
574
+ if (typeof v === "string") v.split(" ").map((cls) => clsx.add(cls));
575
+ else if (Array.isArray(v)) v.map((v2) => v2 && clsx.add(v2));
576
+ else Object.entries(v).map(([k, v2]) => v2 && clsx.add(k));
577
+ }
578
+ for (let cls of cur) if (clsx.has(cls)) clsx.delete(cls);
579
+ else el.classList.remove(cls);
580
+ for (let cls of cur = clsx) el.classList.add(cls);
581
+ })
582
+ );
583
+ }
584
+ });
585
+
586
+ // directive/style.js
587
+ var init_style = __esm({
588
+ "directive/style.js"() {
589
+ init_core();
590
+ dir(
591
+ "style",
592
+ (el, initStyle) => (initStyle = el.getAttribute("style"), (v) => {
593
+ if (typeof v === "string") el.setAttribute("style", initStyle + (initStyle.endsWith(";") ? "" : "; ") + v);
594
+ else {
595
+ if (initStyle) el.setAttribute("style", initStyle);
596
+ for (let k in v) k[0] == "-" ? el.style.setProperty(k, v[k]) : el.style[k] = v[k];
597
+ }
598
+ })
599
+ );
600
+ }
601
+ });
602
+
639
603
  // directive/fx.js
640
604
  var init_fx = __esm({
641
605
  "directive/fx.js"() {
642
606
  init_core();
643
- directive.fx = (el, evaluate, state) => {
644
- return () => evaluate(state);
645
- };
607
+ dir("fx", (_) => (_2) => _2);
646
608
  }
647
609
  });
648
610
 
@@ -651,12 +613,9 @@ var init_aria = __esm({
651
613
  "directive/aria.js"() {
652
614
  init_core();
653
615
  init_default();
654
- directive["aria"] = (el, evaluate, state) => {
655
- const update = (value) => {
656
- for (let key in value) attr(el, "aria-" + dashcase(key), value[key] == null ? null : value[key] + "");
657
- };
658
- return () => update(evaluate(state));
659
- };
616
+ dir("aria", (el) => (value) => {
617
+ for (let key in value) attr(el, "aria-" + dashcase(key), value[key] == null ? null : value[key] + "");
618
+ });
660
619
  }
661
620
  });
662
621
 
@@ -664,12 +623,9 @@ var init_aria = __esm({
664
623
  var init_data = __esm({
665
624
  "directive/data.js"() {
666
625
  init_core();
667
- directive["data"] = (el, evaluate, state) => {
668
- return () => {
669
- let value = evaluate(state);
670
- for (let key in value) el.dataset[key] = value[key];
671
- };
672
- };
626
+ dir("data", (el) => (value) => {
627
+ for (let key in value) el.dataset[key] = value[key];
628
+ });
673
629
  }
674
630
  });
675
631