tutuca 0.13.1 → 0.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -222,11 +222,6 @@ var writeKey = (value, key, next) => {
222
222
  value.add(next);
223
223
  } else value[key] = next;
224
224
  };
225
- var readSeqKey = (value, key, dval = null) => {
226
- const direct = readKey(value, key, NONE);
227
- if (direct !== NONE) return direct;
228
- return typeof value?.get === "function" ? value.get(key, dval) : dval;
229
- };
230
225
  var writeSeqKey = (value, key, next) => {
231
226
  if (value instanceof Map || value instanceof Set || Array.isArray(value) || Object.hasOwn(value, key))
232
227
  writeKey(value, key, next);
@@ -239,7 +234,7 @@ var Step = class {
239
234
  }
240
235
  setDraftValue(_root, _v) {
241
236
  }
242
- enterFrame(stack, _prev, next) {
237
+ enterFrame(stack, next) {
243
238
  return stack.enter(next, {}, true);
244
239
  }
245
240
  toAbstractPathStep() {
@@ -265,7 +260,7 @@ var BindStep = class _BindStep extends Step {
265
260
  lookup(v, _dval) {
266
261
  return v;
267
262
  }
268
- enterFrame(stack, _prev, next) {
263
+ enterFrame(stack, next) {
269
264
  return stack.enter(next, { ...this.binds }, false);
270
265
  }
271
266
  withIndex(i) {
@@ -283,7 +278,7 @@ var ScopeBindStep = class _ScopeBindStep extends BindStep {
283
278
  super(binds);
284
279
  this.val = val;
285
280
  }
286
- enterFrame(stack, _prev, next) {
281
+ enterFrame(stack, next) {
287
282
  const dyn = this.val.evalAsHandler(stack)?.call(stack.it) ?? {};
288
283
  return stack.enter(next, { ...this.binds, ...dyn }, false);
289
284
  }
@@ -322,13 +317,13 @@ var SeqStep = class extends Step {
322
317
  this.key = key;
323
318
  }
324
319
  lookup(v, dval = null) {
325
- return readSeqKey(readKey(v, this.field, null), this.key, dval);
320
+ return seqGet(readKey(v, this.field, null), this.key, dval);
326
321
  }
327
322
  setDraftValue(root, v) {
328
323
  const seq = readKey(root, this.field, null);
329
324
  if (seq != null) writeSeqKey(seq, this.key, v);
330
325
  }
331
- enterFrame(stack, _prev, next) {
326
+ enterFrame(stack, next) {
332
327
  return stack.enter(next, { key: this.key }, true);
333
328
  }
334
329
  toKey() {
@@ -344,7 +339,7 @@ var SeqAccessStep = class extends Step {
344
339
  lookup(v, dval = null) {
345
340
  const seq = readKey(v, this.seqField, NONE);
346
341
  const key = readKey(v, this.keyField, NONE);
347
- return key !== NONE && seq !== NONE ? readSeqKey(seq, key, dval) : dval;
342
+ return key !== NONE && seq !== NONE ? seqGet(seq, key, dval) : dval;
348
343
  }
349
344
  setDraftValue(root, v) {
350
345
  const seq = readKey(root, this.seqField, NONE);
@@ -375,7 +370,7 @@ var EachBindStep = class extends Step {
375
370
  }
376
371
  // Replay the renderer's per-item binds (key, value + any @enrich-with binds)
377
372
  // so a rebuilt stack matches the one @each rendered with.
378
- enterFrame(stack, _prev, next) {
373
+ enterFrame(stack, next) {
379
374
  return stack.enter(next, this.iterInfo.enrichBinds(stack, this.key), false);
380
375
  }
381
376
  toAbstractPathStep() {
@@ -383,7 +378,7 @@ var EachBindStep = class extends Step {
383
378
  }
384
379
  };
385
380
  var EachRenderItStep = class extends SeqStep {
386
- enterFrame(stack, _prev, next) {
381
+ enterFrame(stack, next) {
387
382
  return stack.enter(next, { key: this.key, value: next }, false).enter(next, {}, true);
388
383
  }
389
384
  toAbstractPathStep() {
@@ -408,7 +403,7 @@ var DynStep = class extends Step {
408
403
  warnRawDynStep("lookup", this);
409
404
  return dval;
410
405
  }
411
- enterFrame(stack, _prev, _next) {
406
+ enterFrame(stack, _next) {
412
407
  warnRawDynStep("enterFrame", this);
413
408
  return stack;
414
409
  }
@@ -546,7 +541,7 @@ var Path = class _Path {
546
541
  console.warn("bad PathItem", { root: stack.it, step, path: this });
547
542
  return null;
548
543
  }
549
- stack = step.enterFrame(stack, prev, next);
544
+ stack = step.enterFrame(stack, next);
550
545
  prev = next;
551
546
  }
552
547
  return stack;
@@ -616,10 +611,6 @@ var Path = class _Path {
616
611
  console.warn("event reconstruction: dynamic-var producer not found", pendingDyns);
617
612
  return [new _Path(pathSteps.reverse()), handlers];
618
613
  }
619
- static fromEvent(e, rNode, maxDepth, comps, stopOnNoEvent = true) {
620
- const { type, target } = e;
621
- return _Path.fromNodeAndEventName(target, type, rNode, maxDepth, comps, stopOnNoEvent);
622
- }
623
614
  };
624
615
  function metaChain(n) {
625
616
  const out = [];
@@ -823,31 +814,14 @@ function parseBool(s, px) {
823
814
  const val = parseToken(tokens[0], px);
824
815
  return val !== null && kindOf(val) & G_BOOL ? val : null;
825
816
  }
826
- function parseText(s, px) {
827
- return _parseSingle(s, px, G_TEXT);
828
- }
829
- function parseComponent(s, px) {
830
- return _parseSingle(s, px, G_COMPONENT);
831
- }
832
- function parseSequence(s, px) {
833
- return _parseSingle(s, px, G_SEQUENCE);
834
- }
835
- function parseField(s, px) {
836
- return _parseSingle(s, px, G_FIELD);
837
- }
838
- function parseProvide(s, px) {
839
- return _parseSingle(s, px, G_PROVIDE);
840
- }
841
- function parseMacroAttr(s, px) {
842
- return _parseSingle(s, px, G_ALL);
843
- }
844
- function parseReceiveHandler(s, px) {
845
- return _parseHandler(s, px, "receive", true, true, false);
846
- }
847
- function parseAlterHandler(s, px) {
848
- const r = _parseHandler(s, px, "alter", false, false, true);
849
- return r === null ? null : r.handlerVal;
850
- }
817
+ var parseText = (s, px) => _parseSingle(s, px, G_TEXT);
818
+ var parseComponent = (s, px) => _parseSingle(s, px, G_COMPONENT);
819
+ var parseSequence = (s, px) => _parseSingle(s, px, G_SEQUENCE);
820
+ var parseField = (s, px) => _parseSingle(s, px, G_FIELD);
821
+ var parseProvide = (s, px) => _parseSingle(s, px, G_PROVIDE);
822
+ var parseMacroAttr = (s, px) => _parseSingle(s, px, G_ALL);
823
+ var parseReceiveHandler = (s, px) => _parseHandler(s, px, "receive", true, true, false);
824
+ var parseAlterHandler = (s, px) => _parseHandler(s, px, "alter", false, false, true)?.handlerVal ?? null;
851
825
  function _parseHandler(s, px, namespace, allowArgs, report, allowMethod) {
852
826
  const tokens = tokenizeValue(s.trim());
853
827
  const headTok = tokens[0] ?? "";
@@ -1179,7 +1153,7 @@ var Attributes = class {
1179
1153
  this.items = items;
1180
1154
  }
1181
1155
  static parse(attributes, px, parseAll = false) {
1182
- return getAttrParser(px).parse(attributes, parseAll);
1156
+ return new AttrParser(px).parse(attributes, parseAll);
1183
1157
  }
1184
1158
  isConstant() {
1185
1159
  return false;
@@ -1425,9 +1399,6 @@ var IfAttr = class extends BaseAttr {
1425
1399
  return this.condVal.eval(stack) ? this.thenVal.eval(stack) : this.elseVal.eval(stack);
1426
1400
  }
1427
1401
  };
1428
- function getAttrParser(px) {
1429
- return new AttrParser(px);
1430
- }
1431
1402
  var EventHandler = class _EventHandler {
1432
1403
  constructor(handlerVal, args = []) {
1433
1404
  this.handlerVal = handlerVal;
@@ -1443,12 +1414,6 @@ var EventHandler = class _EventHandler {
1443
1414
  return r === null ? null : new _EventHandler(r.handlerVal, r.args);
1444
1415
  }
1445
1416
  };
1446
- var IntentHandler = class {
1447
- constructor(name, fn) {
1448
- this.name = name;
1449
- this.fn = fn;
1450
- }
1451
- };
1452
1417
 
1453
1418
  // src/iteration.js
1454
1419
  var SEQ_INFO = /* @__PURE__ */ Symbol.for("tutuca.seqInfo");
@@ -1499,6 +1464,15 @@ var callEnricher = (enricher, it, binds, key, value, iterData) => {
1499
1464
  binds.key = key;
1500
1465
  binds.value = value;
1501
1466
  };
1467
+ function bindsForKey({ seq, it, loopWith, enricher, ctx }, key) {
1468
+ const value = seqGet(seq, key, null);
1469
+ const binds = { key, value };
1470
+ if (enricher) {
1471
+ const { iterData } = unpackLoopResult(loopWith.call(it, seq, ctx), seq);
1472
+ callEnricher(enricher, it, binds, key, value, iterData);
1473
+ }
1474
+ return binds;
1475
+ }
1502
1476
  var visitKeys = (seq, keys, visit) => {
1503
1477
  const attrName = isIndexedSeq(seq) ? "si" : "sk";
1504
1478
  for (const key of keys) visit(key, seqGet(seq, key), attrName);
@@ -1536,19 +1510,9 @@ function childOpts(vnode, ns, opts) {
1536
1510
  const target = ns === SVG_NS && isForeignObject(vnode.tag) ? null : ns;
1537
1511
  return target === (opts.namespace ?? null) ? opts : { ...opts, namespace: target };
1538
1512
  }
1539
- var NEVER_ASSIGN = /* @__PURE__ */ new Set([
1540
- "width",
1541
- "height",
1542
- "href",
1543
- "list",
1544
- "form",
1545
- "tabIndex",
1546
- "download",
1547
- "rowSpan",
1548
- "colSpan",
1549
- "role",
1550
- "popover"
1551
- ]);
1513
+ var NEVER_ASSIGN = new Set(
1514
+ "width height href list form tabIndex download rowSpan colSpan role popover".split(" ")
1515
+ );
1552
1516
  var PROP_ATTR_NAME = { className: "class", htmlFor: "for" };
1553
1517
  function applyProperties(node, props) {
1554
1518
  const namespaced = isNamespaced(node);
@@ -1827,6 +1791,10 @@ function morphChildren(parentDom, oldChilds, newChilds, opts) {
1827
1791
  if (!used[i] && domNodes[i].parentNode === parentDom) parentDom.removeChild(domNodes[i]);
1828
1792
  }
1829
1793
  function render(vnode, container, options, prev) {
1794
+ if (vnode == null) {
1795
+ container.replaceChildren();
1796
+ return { vnode: null, dom: null };
1797
+ }
1830
1798
  const isFragment = vnode instanceof VFragment;
1831
1799
  if (prev && prev.vnode instanceof VFragment === isFragment) {
1832
1800
  const oldDom = isFragment ? container : prev.dom;
@@ -2343,20 +2311,11 @@ var IterInfo = class {
2343
2311
  const enricher = this.enrichWithVal?.evalAsHandler(stack) ?? null;
2344
2312
  return { seq, filter, loopWith, enricher };
2345
2313
  }
2346
- // Rebuild the per-item binds for `key`, mirroring renderEachWhen: seed
2347
- // { key, value }, then run @enrich-with (with @loop-with's iterData) if any.
2314
+ // Rebuild the per-item binds for `key` (see iteration.js bindsForKey).
2348
2315
  enrichBinds(stack, key) {
2349
2316
  const { seq, filter, loopWith, enricher } = this.eval(stack);
2350
- const value = seqGet(seq, key, null);
2351
- const binds = { key, value };
2352
- if (enricher) {
2353
- const { iterData } = unpackLoopResult(
2354
- loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)),
2355
- seq
2356
- );
2357
- callEnricher(enricher, stack.it, binds, key, value, iterData);
2358
- }
2359
- return binds;
2317
+ const ctx = makeLoopCtx(stack, filter);
2318
+ return bindsForKey({ seq, it: stack.it, loopWith, enricher, ctx }, key);
2360
2319
  }
2361
2320
  };
2362
2321
  function xOp(consumed = [], { wrappable = false, wrapper = null, ignoresChildren = false } = {}) {
@@ -2552,10 +2511,11 @@ var NodeEvent = class {
2552
2511
  }
2553
2512
  };
2554
2513
  var fwdIfCtxPred = (pred) => (w) => (that, f, args, ctx) => pred(ctx) ? w(that, f, args, ctx) : that;
2555
- var fwdIfKey = (keyName) => fwdIfCtxPred((ctx) => ctx.e.key === keyName);
2556
- var fwdCtrl = fwdIfCtxPred(({ e }) => isMac && e.metaKey || e.ctrlKey);
2557
- var fwdMeta = fwdIfCtxPred(({ e }) => e.metaKey);
2558
- var fwdAlt = fwdIfCtxPred(({ e }) => e.altKey);
2514
+ var fwdIfEventPred = (pred) => fwdIfCtxPred(({ e }) => pred(e));
2515
+ var fwdIfKey = (keyName) => fwdIfEventPred(keyIs(keyName));
2516
+ var fwdCtrl = fwdIfEventPred(macCtrl);
2517
+ var fwdMeta = fwdIfEventPred((e) => e.metaKey);
2518
+ var fwdAlt = fwdIfEventPred((e) => e.altKey);
2559
2519
  var MOD_WRAPPERS_FOR_ANY_EVENT = {
2560
2520
  ctrl: fwdCtrl,
2561
2521
  cmd: fwdCtrl,
@@ -2740,13 +2700,15 @@ var ComponentStack = class _ComponentStack {
2740
2700
  getCompFor(v) {
2741
2701
  return this.comps.getCompFor(v);
2742
2702
  }
2743
- // Handlers that answer an intent's `lex` leg. A name maps to a LIST, because the leg
2744
- // walks: a handler that returns PASS declines and hands the intent to the next one.
2745
- // A bare function is accepted as a one-element list.
2703
+ // Handlers that answer an intent's `lex` leg. A name maps to a LIST of plain
2704
+ // functions, because the leg walks: a handler that returns PASS declines and hands
2705
+ // the intent to the next one. Each runs with no `this` and takes a dispatcher
2706
+ // context as its final argument; resolving answers, throwing fails. A bare function
2707
+ // is accepted as a one-element list.
2746
2708
  registerIntentHandlers(handlers) {
2747
2709
  for (const name in handlers) {
2748
- const fns = Array.isArray(handlers[name]) ? handlers[name] : [handlers[name]];
2749
- this.intentsByName[name] = fns.map((fn) => new IntentHandler(name, fn));
2710
+ const fns = handlers[name];
2711
+ this.intentsByName[name] = Array.isArray(fns) ? fns : [fns];
2750
2712
  }
2751
2713
  }
2752
2714
  // Innermost scope first, then outward. Concatenated rather than first-match, so a
@@ -2776,14 +2738,12 @@ var ComponentStack = class _ComponentStack {
2776
2738
  }
2777
2739
  };
2778
2740
  var ProvideInfo = class {
2779
- constructor(name, val) {
2780
- this.name = name;
2741
+ constructor(val) {
2781
2742
  this.val = val;
2782
2743
  }
2783
2744
  };
2784
2745
  var LookupInfo = class {
2785
- constructor(name, val) {
2786
- this.name = name;
2746
+ constructor(val) {
2787
2747
  this.val = val;
2788
2748
  }
2789
2749
  };
@@ -2831,13 +2791,13 @@ var Component = class {
2831
2791
  continue;
2832
2792
  }
2833
2793
  const val = parseProvide(this._rawProvide[key], ctx);
2834
- if (val) this.provide[key] = new ProvideInfo(key, val);
2794
+ if (val) this.provide[key] = new ProvideInfo(val);
2835
2795
  }
2836
2796
  for (const entry of this._rawLookup) {
2837
2797
  const name = isString(entry) ? entry : isString(entry?.name) ? entry.name : null;
2838
2798
  if (name === null) continue;
2839
2799
  const defStr = isString(entry?.default) ? entry.default : null;
2840
- this.lookup[name] = new LookupInfo(name, defStr === null ? null : parseField(defStr, ctx));
2800
+ this.lookup[name] = new LookupInfo(defStr === null ? null : parseField(defStr, ctx));
2841
2801
  }
2842
2802
  for (const key in this.lookup)
2843
2803
  if (this.provide[key] !== void 0)
@@ -5660,10 +5620,10 @@ var ATTR_VAL_CHECKERS = {
5660
5620
  }
5661
5621
  };
5662
5622
  function checkConsistentAttrVal(lx, val, env, skipNameVal = false, errCtx = null, isRoot = true) {
5663
- const check3 = ATTR_VAL_CHECKERS[val?.constructor.name];
5664
- if (check3 === void 0) return;
5623
+ const check2 = ATTR_VAL_CHECKERS[val?.constructor.name];
5624
+ if (check2 === void 0) return;
5665
5625
  const recurse = (sub) => checkConsistentAttrVal(lx, sub, env, skipNameVal, errCtx, false);
5666
- check3({ lx, val, env, errCtx, skipNameVal, recurse, isRoot });
5626
+ check2({ lx, val, env, errCtx, skipNameVal, recurse, isRoot });
5667
5627
  }
5668
5628
  var NODE_KIND_TO_CTX = {
5669
5629
  RenderTextNode: { originAttr: "<x text>" },
@@ -6109,34 +6069,16 @@ function dispatchPhase(dispatcher, targetPath, phase, self) {
6109
6069
  // src/oo.js
6110
6070
  var BAD_VALUE2 = /* @__PURE__ */ Symbol("BadValue");
6111
6071
  var nullCoercer = (v) => v;
6112
- function defaultToData(v) {
6113
- if (v instanceof Map) return [...v.entries()];
6114
- if (v instanceof Set) return [...v.values()];
6115
- return v;
6116
- }
6117
6072
  var Field = class {
6118
6073
  constructor(type, name, typeCheck, coercer, defaultValue = null) {
6119
6074
  this.type = type;
6120
6075
  this.name = name;
6121
6076
  this.typeCheck = typeCheck;
6122
6077
  this.coercer = coercer;
6123
- this.checks = [];
6124
6078
  this.defaultValue = defaultValue;
6125
6079
  }
6126
- toDataDef() {
6127
- return { type: this.type, defaultValue: defaultToData(this.defaultValue) };
6128
- }
6129
- getFirstFailingCheck(v) {
6130
- if (!this.typeCheck.isValid(v)) return this.typeCheck;
6131
- for (const check3 of this.checks) if (!check3.isValid(v)) return check3;
6132
- return null;
6133
- }
6134
6080
  isValid(v) {
6135
- return this.getFirstFailingCheck(v) === null;
6136
- }
6137
- addCheck(check3) {
6138
- this.checks.push(check3);
6139
- return this;
6081
+ return this.typeCheck(v);
6140
6082
  }
6141
6083
  coerceOr(v, defaultValue = null) {
6142
6084
  if (this.isValid(v)) return v;
@@ -6147,135 +6089,79 @@ var Field = class {
6147
6089
  return this.coerceOr(v, this.defaultValue);
6148
6090
  }
6149
6091
  };
6150
- var Check = class {
6151
- isValid(_v) {
6152
- return true;
6153
- }
6154
- getMessage(_v) {
6155
- return "Invalid";
6156
- }
6157
- };
6158
- var CheckTypeAny = class extends Check {
6159
- };
6160
- var CHECK_TYPE_ANY = new CheckTypeAny();
6161
- var FnCheck = class extends Check {
6162
- constructor(isValidFn, getMessageFn) {
6163
- super();
6164
- this._isValid = isValidFn;
6165
- this._getMessage = getMessageFn;
6166
- }
6167
- isValid(v) {
6168
- return this._isValid(v);
6169
- }
6170
- getMessage(v) {
6171
- return this._getMessage(v);
6172
- }
6092
+ var CHECK_TYPE_ANY = (_v) => true;
6093
+ var CHECK_TYPE_INT = Number.isInteger;
6094
+ var CHECK_TYPE_FLOAT = Number.isFinite;
6095
+ var CHECK_TYPE_BOOL = (v) => typeof v === "boolean";
6096
+ var CHECK_TYPE_STRING = (v) => typeof v === "string";
6097
+ var CHECK_TYPE_LIST = Array.isArray;
6098
+ var CHECK_TYPE_OBJECT = isPlainObject;
6099
+ var CHECK_TYPE_MAP = (v) => v instanceof Map;
6100
+ var CHECK_TYPE_SET = (v) => v instanceof Set;
6101
+ var COERCE_NONE = (_v) => null;
6102
+ var COERCE_BOOL = (v) => !!v;
6103
+ var COERCE_STRING = (v) => v?.toString?.() ?? "";
6104
+ var COERCE_INT = (v) => Number.isFinite(v) ? Math.trunc(v) : null;
6105
+ var COERCE_LIST = (v) => Array.isArray(v) ? [...v] : null;
6106
+ var COERCE_OBJECT = (v) => isPlainObject(v) ? { ...v } : null;
6107
+ var COERCE_MAP = (v) => {
6108
+ if (v instanceof Map) return new Map(v);
6109
+ if (Array.isArray(v) || isPlainObject(v))
6110
+ return new Map(Array.isArray(v) ? v : Object.entries(v));
6111
+ return null;
6173
6112
  };
6174
- var check = (fn, message) => new FnCheck(fn, () => message);
6175
- var CHECK_TYPE_INT = check(Number.isInteger, "Integer expected");
6176
- var CHECK_TYPE_FLOAT = check(Number.isFinite, "Float expected");
6177
- var CHECK_TYPE_BOOL = check((v) => typeof v === "boolean", "Boolean expected");
6178
- var CHECK_TYPE_STRING = check((v) => typeof v === "string", "String expected");
6179
- var CHECK_TYPE_LIST = check(Array.isArray, "Array expected");
6180
- var CHECK_TYPE_OBJECT = check(isPlainObject, "Plain object expected");
6181
- var CHECK_TYPE_MAP = check((v) => v instanceof Map, "Map expected");
6182
- var CHECK_TYPE_SET = check((v) => v instanceof Set, "Set expected");
6113
+ var COERCE_SET = (v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null;
6183
6114
  var FieldBool = class extends Field {
6184
6115
  constructor(name, defaultValue = false) {
6185
- super("bool", name, CHECK_TYPE_BOOL, (v) => !!v, defaultValue);
6116
+ super("bool", name, CHECK_TYPE_BOOL, COERCE_BOOL, defaultValue);
6186
6117
  }
6187
6118
  };
6188
6119
  var FieldAny = class extends Field {
6189
6120
  constructor(name, defaultValue = null) {
6190
6121
  super("any", name, CHECK_TYPE_ANY, nullCoercer, defaultValue);
6191
6122
  }
6192
- toDataDef() {
6193
- return { type: getTypeName(this.defaultValue) ?? "any", defaultValue: this.defaultValue };
6194
- }
6195
6123
  };
6196
6124
  var FieldString = class extends Field {
6197
6125
  constructor(name, defaultValue = "") {
6198
- super("text", name, CHECK_TYPE_STRING, (v) => v?.toString?.() ?? "", defaultValue);
6126
+ super("text", name, CHECK_TYPE_STRING, COERCE_STRING, defaultValue);
6199
6127
  }
6200
6128
  };
6201
6129
  var FieldInt = class extends Field {
6202
6130
  constructor(name, defaultValue = 0) {
6203
- super(
6204
- "int",
6205
- name,
6206
- CHECK_TYPE_INT,
6207
- (v) => Number.isFinite(v) ? Math.trunc(v) : null,
6208
- defaultValue
6209
- );
6131
+ super("int", name, CHECK_TYPE_INT, COERCE_INT, defaultValue);
6210
6132
  }
6211
6133
  };
6212
6134
  var FieldFloat = class extends Field {
6213
6135
  constructor(name, defaultValue = 0) {
6214
- super("float", name, CHECK_TYPE_FLOAT, (_) => null, defaultValue);
6215
- }
6216
- };
6217
- var getTypeName = (v) => v?.constructor?.[COMPONENT]?.name ?? v?.constructor?.getMetaClass?.()?.name ?? null;
6218
- var CheckTypeName = class {
6219
- constructor(typeName) {
6220
- this.typeName = typeName;
6221
- }
6222
- isValid(v) {
6223
- return getTypeName(v) === this.typeName;
6224
- }
6225
- getMessage(v) {
6226
- return `Expected "${this.typeName}", got "${getTypeName(v)}"`;
6136
+ super("float", name, CHECK_TYPE_FLOAT, COERCE_NONE, defaultValue);
6227
6137
  }
6228
6138
  };
6139
+ var metaOf = (v) => v?.constructor?.[COMPONENT] ?? v?.constructor?.getMetaClass?.();
6140
+ var getTypeName = (v) => metaOf(v)?.name ?? null;
6229
6141
  var FieldComp = class extends Field {
6230
6142
  constructor(type, name, args) {
6231
- super(type, name, new CheckTypeName(type), nullCoercer, null);
6143
+ super(type, name, (v) => getTypeName(v) === type, nullCoercer, null);
6232
6144
  this.args = args;
6233
6145
  }
6234
- toDataDef() {
6235
- return { component: this.type, args: this.args };
6236
- }
6237
6146
  };
6238
6147
  var FieldList = class extends Field {
6239
6148
  constructor(name, defaultValue = []) {
6240
- super("list", name, CHECK_TYPE_LIST, (v) => Array.isArray(v) ? [...v] : null, defaultValue);
6149
+ super("list", name, CHECK_TYPE_LIST, COERCE_LIST, defaultValue);
6241
6150
  }
6242
6151
  };
6243
6152
  var FieldObject = class extends Field {
6244
6153
  constructor(name, defaultValue = {}) {
6245
- super(
6246
- "object",
6247
- name,
6248
- CHECK_TYPE_OBJECT,
6249
- (v) => isPlainObject(v) ? { ...v } : null,
6250
- defaultValue
6251
- );
6154
+ super("object", name, CHECK_TYPE_OBJECT, COERCE_OBJECT, defaultValue);
6252
6155
  }
6253
6156
  };
6254
6157
  var FieldMap = class extends Field {
6255
6158
  constructor(name, defaultValue = /* @__PURE__ */ new Map()) {
6256
- super(
6257
- "map",
6258
- name,
6259
- CHECK_TYPE_MAP,
6260
- (v) => {
6261
- if (v instanceof Map) return new Map(v);
6262
- if (Array.isArray(v) || isPlainObject(v))
6263
- return new Map(Array.isArray(v) ? v : Object.entries(v));
6264
- return null;
6265
- },
6266
- defaultValue
6267
- );
6159
+ super("map", name, CHECK_TYPE_MAP, COERCE_MAP, defaultValue);
6268
6160
  }
6269
6161
  };
6270
6162
  var FieldSet = class extends Field {
6271
6163
  constructor(name, defaultValue = /* @__PURE__ */ new Set()) {
6272
- super(
6273
- "set",
6274
- name,
6275
- CHECK_TYPE_SET,
6276
- (v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null,
6277
- defaultValue
6278
- );
6164
+ super("set", name, CHECK_TYPE_SET, COERCE_SET, defaultValue);
6279
6165
  }
6280
6166
  };
6281
6167
  function mkCompField(field, scope, args) {
@@ -6373,8 +6259,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
6373
6259
  const value = fields[field];
6374
6260
  const type = typeof value;
6375
6261
  if (type === "string") b.addField(field, value, FieldString);
6376
- else if (type === "number")
6377
- b.addField(field, value, Number.isInteger(value) ? FieldInt : FieldFloat);
6262
+ else if (type === "number") b.addField(field, value, FieldFloat);
6378
6263
  else if (type === "boolean") b.addField(field, value, FieldBool);
6379
6264
  else if (Array.isArray(value)) b.addField(field, [...value], FieldList);
6380
6265
  else if (value instanceof Set) b.addField(field, new Set(value), FieldSet);
@@ -6395,7 +6280,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
6395
6280
  return b.build();
6396
6281
  }
6397
6282
  function validateDraftFields(current, draft) {
6398
- const meta = current?.constructor?.[COMPONENT] ?? current?.constructor?.getMetaClass?.();
6283
+ const meta = metaOf(current);
6399
6284
  if (!meta) return;
6400
6285
  for (const [name, field] of Object.entries(meta.fields)) {
6401
6286
  const value = draft[name];
@@ -6454,7 +6339,7 @@ var component = (opts) => Component.fromSpec(opts);
6454
6339
  // src/stack.js
6455
6340
  var STOP = /* @__PURE__ */ Symbol("STOP");
6456
6341
  var NEXT = /* @__PURE__ */ Symbol("NEXT");
6457
- var DEFAULT_LOOKUP_ROUTE = ["dyn", "lex"];
6342
+ var DEFAULT_ROUTE = ["dyn", "lex"];
6458
6343
  function routeLookup(route, lex, dyn) {
6459
6344
  for (let i = 0; i < route.length; i++) {
6460
6345
  const leg = route[i];
@@ -6576,20 +6461,6 @@ var Stack = class _Stack {
6576
6461
  lookupBind(name) {
6577
6462
  return lookup(this.binds, name);
6578
6463
  }
6579
- // The `lex` leg: what a name means in the registration scope of the component being
6580
- // rendered. The scope chain holds components, so this leg only ever answers for a
6581
- // type name — for a value name it is a miss, which is why one default route serves
6582
- // both. Guarded: a non-component `it` has no scope to ask.
6583
- _lookupLex(name) {
6584
- return this.comps.getCompFor(this.it)?.scope.lookupComponent(name) ?? null;
6585
- }
6586
- lookupRouted(name, route = DEFAULT_LOOKUP_ROUTE) {
6587
- return routeLookup(
6588
- route,
6589
- () => this._lookupLex(name),
6590
- () => this.lookupDynamic(name)
6591
- );
6592
- }
6593
6464
  lookupFieldRaw(name) {
6594
6465
  return this.it[name] ?? null;
6595
6466
  }
@@ -6690,28 +6561,46 @@ var Transactor = class {
6690
6561
  if (i !== -1) this._refusalObservers.splice(i, 1);
6691
6562
  };
6692
6563
  }
6693
- // Build and dispatch the observer record for a settled transaction. The
6694
- // resolved handler (`_resolvedHandler`/`_matched`) and per-leaf before/after
6695
- // (`_before`/`_after`) were captured while the handler ran (see callHandler /
6696
- // Transaction.run). No-op when nobody is observing.
6564
+ // Build and dispatch one observer record. Pins field-resolved keys (e.g. a
6565
+ // `.a[.selId]` render target reconstructed from a DOM event) against the root the
6566
+ // handler read, so pathKeys carries concrete keys instead of dropping the dynamic
6567
+ // step. No-op when nobody is observing.
6568
+ _emitRecord(root, { kind, name, args, path, targetPath, handler, handlerName, matched, before, after, parent }) {
6569
+ if (this._observers.length === 0) return;
6570
+ const pinned = path.pinKeys(root);
6571
+ this._emit({
6572
+ kind,
6573
+ name,
6574
+ args: args ?? null,
6575
+ path: pinned,
6576
+ pathKeys: pinned.toKeys(),
6577
+ targetPath,
6578
+ handler: handler ?? null,
6579
+ handlerName: handlerName ?? (handler?.name || null),
6580
+ matched: matched ?? null,
6581
+ before,
6582
+ after,
6583
+ parent,
6584
+ timestamp: Date.now()
6585
+ });
6586
+ }
6587
+ // The observer record for a settled transaction. The resolved handler
6588
+ // (`_resolvedHandler`/`_matched`) and per-leaf before/after (`_before`/`_after`)
6589
+ // were captured while the handler ran (see callHandler / Transaction.run).
6697
6590
  _emitTransaction(transaction, root) {
6698
6591
  if (this._observers.length === 0) return;
6699
6592
  if (transaction._resolvedHandler === void 0) return;
6700
- const path = transaction.getTransactionPath().pinKeys(root);
6701
- this._emit({
6593
+ this._emitRecord(root, {
6702
6594
  kind: transaction.observeKind,
6703
6595
  name: transaction.observeName,
6704
- args: transaction.args ?? null,
6705
- path,
6706
- pathKeys: path.toKeys(),
6596
+ args: transaction.args,
6597
+ path: transaction.getTransactionPath(),
6707
6598
  targetPath: transaction.targetPath ?? transaction.path,
6708
- handler: transaction._resolvedHandler ?? null,
6709
- handlerName: transaction._resolvedHandler?.name || null,
6710
- matched: transaction._matched ?? null,
6599
+ handler: transaction._resolvedHandler,
6600
+ matched: transaction._matched,
6711
6601
  before: transaction._before,
6712
6602
  after: transaction._after,
6713
- parent: transaction.parentTransaction,
6714
- timestamp: Date.now()
6603
+ parent: transaction.parentTransaction
6715
6604
  });
6716
6605
  }
6717
6606
  // Make `child` a tracked unit of `parent`'s subtree: the parent's completion stays open
@@ -6809,7 +6698,7 @@ var Transaction = class {
6809
6698
  // rather than throwing, so a stray call from the wrong place is a message and not a
6810
6699
  // crash. `walk` is undefined here, which is how ctx.reply/ctx.fail tell the two apart.
6811
6700
  stop() {
6812
- console.warn('ctx.stop() is only meaningful in an "intent" handler - ignored');
6701
+ warnNotIntent("stop");
6813
6702
  }
6814
6703
  forward(_opts) {
6815
6704
  console.warn('ctx.forward() needs a "receive" or "intent" handler - ignored');
@@ -6894,11 +6783,8 @@ var InputEvent = class extends Transaction {
6894
6783
  }
6895
6784
  this.transactor.pushIntent(this.dispatchPath, name, args, rest, this);
6896
6785
  }
6897
- buildStack(root, comps) {
6898
- return this.path.toTransactionPath().buildStack(Stack.root(comps, root, this));
6899
- }
6900
6786
  getHandlerAndArgs(root, _instance, comps) {
6901
- const stack = this.buildStack(root, comps);
6787
+ const stack = this.path.toTransactionPath().buildStack(Stack.root(comps, root, this));
6902
6788
  const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
6903
6789
  this._handlerArgs = [...args];
6904
6790
  const path = this.dispatchPath;
@@ -7000,7 +6886,6 @@ var IntentEvent = class extends NameArgsTransaction {
7000
6886
  };
7001
6887
  var PASS = /* @__PURE__ */ Symbol.for("tutuca.intent.pass");
7002
6888
  var REFUSAL_RING_CAP = 200;
7003
- var DEFAULT_ROUTE = ["dyn", "lex"];
7004
6889
  var INTENT_DEPTH = 64;
7005
6890
  var IntentWalk = class {
7006
6891
  constructor(transactor, path, name, args, opts, parent, release) {
@@ -7049,24 +6934,19 @@ var IntentWalk = class {
7049
6934
  const txnPath = this.origin.toTransactionPath();
7050
6935
  const leaf = txnPath.lookup(root);
7051
6936
  const chain = this.transactor.comps.getIntentChainFor(leaf, this.name);
7052
- if (this.transactor._observers.length > 0) {
7053
- const path = txnPath.pinKeys(root);
7054
- this.transactor._emit({
7055
- kind: "intent",
7056
- name: this.name,
7057
- args: this.args,
7058
- path,
7059
- pathKeys: path.toKeys(),
7060
- targetPath: this.origin,
7061
- handler: chain[0]?.fn ?? null,
7062
- handlerName: chain[0]?.fn?.name || this.name,
7063
- matched: chain.length > 0 ? "exact" : "none",
7064
- before: leaf,
7065
- after: void 0,
7066
- parent: this.parent,
7067
- timestamp: Date.now()
7068
- });
7069
- }
6937
+ this.transactor._emitRecord(root, {
6938
+ kind: "intent",
6939
+ name: this.name,
6940
+ args: this.args,
6941
+ path: txnPath,
6942
+ targetPath: this.origin,
6943
+ handler: chain[0],
6944
+ handlerName: chain[0]?.name || this.name,
6945
+ matched: chain.length > 0 ? "exact" : "none",
6946
+ before: leaf,
6947
+ after: void 0,
6948
+ parent: this.parent
6949
+ });
7070
6950
  if (chain.length === 0) return this.advance();
7071
6951
  const p = this._runLex(chain, 0);
7072
6952
  this.transactor._inflight.add(p);
@@ -7077,7 +6957,7 @@ var IntentWalk = class {
7077
6957
  if (i >= chain.length) return this.advance();
7078
6958
  const ctx = new Dispatcher(this.origin, this.transactor, this.parent);
7079
6959
  try {
7080
- const res = await chain[i].fn.apply(null, [...this.args, ctx]);
6960
+ const res = await chain[i].apply(null, [...this.args, ctx]);
7081
6961
  if (res === PASS) return this._runLex(chain, i + 1);
7082
6962
  this.answer("Ok", res);
7083
6963
  } catch (error) {
@@ -7230,9 +7110,8 @@ var Dispatcher = class {
7230
7110
  // the same spelling as `ctx.intent` — `["dyn"]` the render ancestry, `["lex"]` the
7231
7111
  // registration scope, default both.
7232
7112
  lookup(name, opts) {
7233
- const route = opts?.route ?? DEFAULT_LOOKUP_ROUTE;
7234
7113
  return routeLookup(
7235
- route,
7114
+ opts?.route ?? DEFAULT_ROUTE,
7236
7115
  () => this._lookupLex(name),
7237
7116
  () => this._stack()?.lookupDynamic(name) ?? null
7238
7117
  );
@@ -7251,12 +7130,10 @@ var Dispatcher = class {
7251
7130
  // can only ever answer with one; the `dyn` leg reads a binding an ancestor
7252
7131
  // published, so it is the leg that has to be checked.
7253
7132
  lookupType(name, opts) {
7254
- const v = this.lookup(name, opts);
7133
+ const route = opts?.route ?? DEFAULT_ROUTE;
7134
+ const v = this.lookup(name, { route });
7255
7135
  if (v == null) {
7256
- this.transactor.refuse("TYPE_NOT_FOUND", {
7257
- name,
7258
- route: opts?.route ?? DEFAULT_LOOKUP_ROUTE
7259
- });
7136
+ this.transactor.refuse("TYPE_NOT_FOUND", { name, route });
7260
7137
  return null;
7261
7138
  }
7262
7139
  if (v?.[COMPONENT] == null) {
@@ -8058,7 +7935,14 @@ var App = class {
8058
7935
  const { type } = e;
8059
7936
  const isDrag = type === "dragover" || type === "dragstart" || type === "dragend" || type === "drop";
8060
7937
  const { rootNode: root, maxEventNodeDepth: maxDepth, comps, transactor } = this;
8061
- const [path, handlers] = Path.fromEvent(e, root, maxDepth, comps, !isDrag);
7938
+ const [path, handlers] = Path.fromNodeAndEventName(
7939
+ e.target,
7940
+ type,
7941
+ root,
7942
+ maxDepth,
7943
+ comps,
7944
+ !isDrag
7945
+ );
8062
7946
  if (isDrag) this._handleDragEvent(e, type, path);
8063
7947
  if (path !== null && handlers !== null)
8064
7948
  for (const handler of handlers) transactor.transactInputNow(path, e, handler, this.dragInfo);
@@ -8120,7 +8004,7 @@ var App = class {
8120
8004
  const value = txnPath.lookup(rootValue);
8121
8005
  const dragType = e.target.dataset.dragtype ?? "?";
8122
8006
  const stack = path.toTransactionPath().buildStack(this.makeStack(rootValue));
8123
- this.dragInfo = new DragInfo(txnPath, stack, e, value, dragType, e.target);
8007
+ this.dragInfo = new DragInfo(stack, value, dragType, e.target);
8124
8008
  } else if (type === "drop") {
8125
8009
  e.preventDefault();
8126
8010
  this._cleanDragOverAttrs();
@@ -8257,10 +8141,8 @@ function getClosestDropTarget(target, rootNode, count) {
8257
8141
  return null;
8258
8142
  }
8259
8143
  var DragInfo = class {
8260
- constructor(path, stack, e, val, type, node) {
8261
- this.path = path;
8144
+ constructor(stack, val, type, node) {
8262
8145
  this.stack = stack;
8263
- this.e = e;
8264
8146
  this.val = val;
8265
8147
  this.type = type;
8266
8148
  this.node = node;
@@ -8352,6 +8234,8 @@ var Renderer = class {
8352
8234
  setNullCache() {
8353
8235
  this.cache = new NullDomCache();
8354
8236
  }
8237
+ // Library utilities for consumers embedding tutuca: render a value to a detached
8238
+ // DOM node / an HTML string. Not called by the framework itself.
8355
8239
  renderToDOM(stack, val) {
8356
8240
  const rootNode = document.createElement("div");
8357
8241
  const rOpts = { document };
@@ -8569,7 +8453,7 @@ function shadowCheckComponent(Comp) {
8569
8453
  });
8570
8454
  return checkComponent(shadowComp).reports;
8571
8455
  }
8572
- function check2(app) {
8456
+ function check(app) {
8573
8457
  const counts = { error: 0, warn: 0, hint: 0 };
8574
8458
  for (const Comp of app.comps.byId.values()) {
8575
8459
  const reports = shadowCheckComponent(Comp);
@@ -8694,7 +8578,7 @@ export {
8694
8578
  UNKNOWN_X_OP,
8695
8579
  UNSUPPORTED_EXPR_SYNTAX,
8696
8580
  X_OP_IGNORES_CHILDREN,
8697
- check2 as check,
8581
+ check,
8698
8582
  checkComponent,
8699
8583
  collectIterBindings,
8700
8584
  compileClassesToStyle,