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.
@@ -4967,11 +4967,6 @@ var writeKey = (value, key, next) => {
4967
4967
  value.add(next);
4968
4968
  } else value[key] = next;
4969
4969
  };
4970
- var readSeqKey = (value, key, dval = null) => {
4971
- const direct = readKey(value, key, NONE);
4972
- if (direct !== NONE) return direct;
4973
- return typeof value?.get === "function" ? value.get(key, dval) : dval;
4974
- };
4975
4970
  var writeSeqKey = (value, key, next) => {
4976
4971
  if (value instanceof Map || value instanceof Set || Array.isArray(value) || Object.hasOwn(value, key))
4977
4972
  writeKey(value, key, next);
@@ -4984,7 +4979,7 @@ var Step = class {
4984
4979
  }
4985
4980
  setDraftValue(_root, _v) {
4986
4981
  }
4987
- enterFrame(stack, _prev, next) {
4982
+ enterFrame(stack, next) {
4988
4983
  return stack.enter(next, {}, true);
4989
4984
  }
4990
4985
  toAbstractPathStep() {
@@ -5010,7 +5005,7 @@ var BindStep = class _BindStep extends Step {
5010
5005
  lookup(v, _dval) {
5011
5006
  return v;
5012
5007
  }
5013
- enterFrame(stack, _prev, next) {
5008
+ enterFrame(stack, next) {
5014
5009
  return stack.enter(next, { ...this.binds }, false);
5015
5010
  }
5016
5011
  withIndex(i) {
@@ -5028,7 +5023,7 @@ var ScopeBindStep = class _ScopeBindStep extends BindStep {
5028
5023
  super(binds);
5029
5024
  this.val = val;
5030
5025
  }
5031
- enterFrame(stack, _prev, next) {
5026
+ enterFrame(stack, next) {
5032
5027
  const dyn = this.val.evalAsHandler(stack)?.call(stack.it) ?? {};
5033
5028
  return stack.enter(next, { ...this.binds, ...dyn }, false);
5034
5029
  }
@@ -5067,13 +5062,13 @@ var SeqStep = class extends Step {
5067
5062
  this.key = key;
5068
5063
  }
5069
5064
  lookup(v, dval = null) {
5070
- return readSeqKey(readKey(v, this.field, null), this.key, dval);
5065
+ return seqGet(readKey(v, this.field, null), this.key, dval);
5071
5066
  }
5072
5067
  setDraftValue(root, v) {
5073
5068
  const seq = readKey(root, this.field, null);
5074
5069
  if (seq != null) writeSeqKey(seq, this.key, v);
5075
5070
  }
5076
- enterFrame(stack, _prev, next) {
5071
+ enterFrame(stack, next) {
5077
5072
  return stack.enter(next, { key: this.key }, true);
5078
5073
  }
5079
5074
  toKey() {
@@ -5089,7 +5084,7 @@ var SeqAccessStep = class extends Step {
5089
5084
  lookup(v, dval = null) {
5090
5085
  const seq = readKey(v, this.seqField, NONE);
5091
5086
  const key = readKey(v, this.keyField, NONE);
5092
- return key !== NONE && seq !== NONE ? readSeqKey(seq, key, dval) : dval;
5087
+ return key !== NONE && seq !== NONE ? seqGet(seq, key, dval) : dval;
5093
5088
  }
5094
5089
  setDraftValue(root, v) {
5095
5090
  const seq = readKey(root, this.seqField, NONE);
@@ -5120,7 +5115,7 @@ var EachBindStep = class extends Step {
5120
5115
  }
5121
5116
  // Replay the renderer's per-item binds (key, value + any @enrich-with binds)
5122
5117
  // so a rebuilt stack matches the one @each rendered with.
5123
- enterFrame(stack, _prev, next) {
5118
+ enterFrame(stack, next) {
5124
5119
  return stack.enter(next, this.iterInfo.enrichBinds(stack, this.key), false);
5125
5120
  }
5126
5121
  toAbstractPathStep() {
@@ -5128,7 +5123,7 @@ var EachBindStep = class extends Step {
5128
5123
  }
5129
5124
  };
5130
5125
  var EachRenderItStep = class extends SeqStep {
5131
- enterFrame(stack, _prev, next) {
5126
+ enterFrame(stack, next) {
5132
5127
  return stack.enter(next, { key: this.key, value: next }, false).enter(next, {}, true);
5133
5128
  }
5134
5129
  toAbstractPathStep() {
@@ -5153,7 +5148,7 @@ var DynStep = class extends Step {
5153
5148
  warnRawDynStep("lookup", this);
5154
5149
  return dval;
5155
5150
  }
5156
- enterFrame(stack, _prev, _next) {
5151
+ enterFrame(stack, _next) {
5157
5152
  warnRawDynStep("enterFrame", this);
5158
5153
  return stack;
5159
5154
  }
@@ -5291,7 +5286,7 @@ var Path = class _Path {
5291
5286
  console.warn("bad PathItem", { root: stack.it, step, path: this });
5292
5287
  return null;
5293
5288
  }
5294
- stack = step.enterFrame(stack, prev, next);
5289
+ stack = step.enterFrame(stack, next);
5295
5290
  prev = next;
5296
5291
  }
5297
5292
  return stack;
@@ -5361,10 +5356,6 @@ var Path = class _Path {
5361
5356
  console.warn("event reconstruction: dynamic-var producer not found", pendingDyns);
5362
5357
  return [new _Path(pathSteps.reverse()), handlers];
5363
5358
  }
5364
- static fromEvent(e, rNode, maxDepth, comps, stopOnNoEvent = true) {
5365
- const { type: type3, target } = e;
5366
- return _Path.fromNodeAndEventName(target, type3, rNode, maxDepth, comps, stopOnNoEvent);
5367
- }
5368
5359
  };
5369
5360
  function metaChain(n) {
5370
5361
  const out = [];
@@ -5568,31 +5559,14 @@ function parseBool(s, px) {
5568
5559
  const val = parseToken(tokens[0], px);
5569
5560
  return val !== null && kindOf(val) & G_BOOL ? val : null;
5570
5561
  }
5571
- function parseText(s, px) {
5572
- return _parseSingle(s, px, G_TEXT);
5573
- }
5574
- function parseComponent(s, px) {
5575
- return _parseSingle(s, px, G_COMPONENT);
5576
- }
5577
- function parseSequence(s, px) {
5578
- return _parseSingle(s, px, G_SEQUENCE);
5579
- }
5580
- function parseField(s, px) {
5581
- return _parseSingle(s, px, G_FIELD);
5582
- }
5583
- function parseProvide(s, px) {
5584
- return _parseSingle(s, px, G_PROVIDE);
5585
- }
5586
- function parseMacroAttr(s, px) {
5587
- return _parseSingle(s, px, G_ALL);
5588
- }
5589
- function parseReceiveHandler(s, px) {
5590
- return _parseHandler(s, px, "receive", true, true, false);
5591
- }
5592
- function parseAlterHandler(s, px) {
5593
- const r = _parseHandler(s, px, "alter", false, false, true);
5594
- return r === null ? null : r.handlerVal;
5595
- }
5562
+ var parseText = (s, px) => _parseSingle(s, px, G_TEXT);
5563
+ var parseComponent = (s, px) => _parseSingle(s, px, G_COMPONENT);
5564
+ var parseSequence = (s, px) => _parseSingle(s, px, G_SEQUENCE);
5565
+ var parseField = (s, px) => _parseSingle(s, px, G_FIELD);
5566
+ var parseProvide = (s, px) => _parseSingle(s, px, G_PROVIDE);
5567
+ var parseMacroAttr = (s, px) => _parseSingle(s, px, G_ALL);
5568
+ var parseReceiveHandler = (s, px) => _parseHandler(s, px, "receive", true, true, false);
5569
+ var parseAlterHandler = (s, px) => _parseHandler(s, px, "alter", false, false, true)?.handlerVal ?? null;
5596
5570
  function _parseHandler(s, px, namespace, allowArgs, report, allowMethod) {
5597
5571
  const tokens = tokenizeValue(s.trim());
5598
5572
  const headTok = tokens[0] ?? "";
@@ -5924,7 +5898,7 @@ var Attributes = class {
5924
5898
  this.items = items;
5925
5899
  }
5926
5900
  static parse(attributes, px, parseAll = false) {
5927
- return getAttrParser(px).parse(attributes, parseAll);
5901
+ return new AttrParser(px).parse(attributes, parseAll);
5928
5902
  }
5929
5903
  isConstant() {
5930
5904
  return false;
@@ -6170,9 +6144,6 @@ var IfAttr = class extends BaseAttr {
6170
6144
  return this.condVal.eval(stack) ? this.thenVal.eval(stack) : this.elseVal.eval(stack);
6171
6145
  }
6172
6146
  };
6173
- function getAttrParser(px) {
6174
- return new AttrParser(px);
6175
- }
6176
6147
  var EventHandler = class _EventHandler {
6177
6148
  constructor(handlerVal, args = []) {
6178
6149
  this.handlerVal = handlerVal;
@@ -6188,12 +6159,6 @@ var EventHandler = class _EventHandler {
6188
6159
  return r === null ? null : new _EventHandler(r.handlerVal, r.args);
6189
6160
  }
6190
6161
  };
6191
- var IntentHandler = class {
6192
- constructor(name, fn) {
6193
- this.name = name;
6194
- this.fn = fn;
6195
- }
6196
- };
6197
6162
 
6198
6163
  // src/iteration.js
6199
6164
  var SEQ_INFO = /* @__PURE__ */ Symbol.for("tutuca.seqInfo");
@@ -6244,6 +6209,15 @@ var callEnricher = (enricher, it, binds, key, value, iterData) => {
6244
6209
  binds.key = key;
6245
6210
  binds.value = value;
6246
6211
  };
6212
+ function bindsForKey({ seq, it, loopWith, enricher, ctx }, key) {
6213
+ const value = seqGet(seq, key, null);
6214
+ const binds = { key, value };
6215
+ if (enricher) {
6216
+ const { iterData } = unpackLoopResult(loopWith.call(it, seq, ctx), seq);
6217
+ callEnricher(enricher, it, binds, key, value, iterData);
6218
+ }
6219
+ return binds;
6220
+ }
6247
6221
  var visitKeys = (seq, keys, visit) => {
6248
6222
  const attrName = isIndexedSeq(seq) ? "si" : "sk";
6249
6223
  for (const key of keys) visit(key, seqGet(seq, key), attrName);
@@ -6281,19 +6255,9 @@ function childOpts(vnode, ns, opts) {
6281
6255
  const target = ns === SVG_NS && isForeignObject(vnode.tag) ? null : ns;
6282
6256
  return target === (opts.namespace ?? null) ? opts : { ...opts, namespace: target };
6283
6257
  }
6284
- var NEVER_ASSIGN = /* @__PURE__ */ new Set([
6285
- "width",
6286
- "height",
6287
- "href",
6288
- "list",
6289
- "form",
6290
- "tabIndex",
6291
- "download",
6292
- "rowSpan",
6293
- "colSpan",
6294
- "role",
6295
- "popover"
6296
- ]);
6258
+ var NEVER_ASSIGN = new Set(
6259
+ "width height href list form tabIndex download rowSpan colSpan role popover".split(" ")
6260
+ );
6297
6261
  var PROP_ATTR_NAME = { className: "class", htmlFor: "for" };
6298
6262
  function applyProperties(node, props) {
6299
6263
  const namespaced = isNamespaced(node);
@@ -6572,6 +6536,10 @@ function morphChildren(parentDom, oldChilds, newChilds, opts) {
6572
6536
  if (!used2[i] && domNodes[i].parentNode === parentDom) parentDom.removeChild(domNodes[i]);
6573
6537
  }
6574
6538
  function render(vnode, container, options, prev) {
6539
+ if (vnode == null) {
6540
+ container.replaceChildren();
6541
+ return { vnode: null, dom: null };
6542
+ }
6575
6543
  const isFragment = vnode instanceof VFragment;
6576
6544
  if (prev && prev.vnode instanceof VFragment === isFragment) {
6577
6545
  const oldDom = isFragment ? container : prev.dom;
@@ -7088,20 +7056,11 @@ var IterInfo = class {
7088
7056
  const enricher = this.enrichWithVal?.evalAsHandler(stack) ?? null;
7089
7057
  return { seq, filter, loopWith, enricher };
7090
7058
  }
7091
- // Rebuild the per-item binds for `key`, mirroring renderEachWhen: seed
7092
- // { key, value }, then run @enrich-with (with @loop-with's iterData) if any.
7059
+ // Rebuild the per-item binds for `key` (see iteration.js bindsForKey).
7093
7060
  enrichBinds(stack, key) {
7094
7061
  const { seq, filter, loopWith, enricher } = this.eval(stack);
7095
- const value = seqGet(seq, key, null);
7096
- const binds = { key, value };
7097
- if (enricher) {
7098
- const { iterData } = unpackLoopResult(
7099
- loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)),
7100
- seq
7101
- );
7102
- callEnricher(enricher, stack.it, binds, key, value, iterData);
7103
- }
7104
- return binds;
7062
+ const ctx = makeLoopCtx(stack, filter);
7063
+ return bindsForKey({ seq, it: stack.it, loopWith, enricher, ctx }, key);
7105
7064
  }
7106
7065
  };
7107
7066
  function xOp(consumed = [], { wrappable = false, wrapper = null, ignoresChildren = false } = {}) {
@@ -7297,10 +7256,11 @@ var NodeEvent = class {
7297
7256
  }
7298
7257
  };
7299
7258
  var fwdIfCtxPred = (pred) => (w) => (that, f, args, ctx) => pred(ctx) ? w(that, f, args, ctx) : that;
7300
- var fwdIfKey = (keyName) => fwdIfCtxPred((ctx) => ctx.e.key === keyName);
7301
- var fwdCtrl = fwdIfCtxPred(({ e }) => isMac && e.metaKey || e.ctrlKey);
7302
- var fwdMeta = fwdIfCtxPred(({ e }) => e.metaKey);
7303
- var fwdAlt = fwdIfCtxPred(({ e }) => e.altKey);
7259
+ var fwdIfEventPred = (pred) => fwdIfCtxPred(({ e }) => pred(e));
7260
+ var fwdIfKey = (keyName) => fwdIfEventPred(keyIs(keyName));
7261
+ var fwdCtrl = fwdIfEventPred(macCtrl);
7262
+ var fwdMeta = fwdIfEventPred((e) => e.metaKey);
7263
+ var fwdAlt = fwdIfEventPred((e) => e.altKey);
7304
7264
  var MOD_WRAPPERS_FOR_ANY_EVENT = {
7305
7265
  ctrl: fwdCtrl,
7306
7266
  cmd: fwdCtrl,
@@ -7485,13 +7445,15 @@ var ComponentStack = class _ComponentStack {
7485
7445
  getCompFor(v) {
7486
7446
  return this.comps.getCompFor(v);
7487
7447
  }
7488
- // Handlers that answer an intent's `lex` leg. A name maps to a LIST, because the leg
7489
- // walks: a handler that returns PASS declines and hands the intent to the next one.
7490
- // A bare function is accepted as a one-element list.
7448
+ // Handlers that answer an intent's `lex` leg. A name maps to a LIST of plain
7449
+ // functions, because the leg walks: a handler that returns PASS declines and hands
7450
+ // the intent to the next one. Each runs with no `this` and takes a dispatcher
7451
+ // context as its final argument; resolving answers, throwing fails. A bare function
7452
+ // is accepted as a one-element list.
7491
7453
  registerIntentHandlers(handlers) {
7492
7454
  for (const name in handlers) {
7493
- const fns = Array.isArray(handlers[name]) ? handlers[name] : [handlers[name]];
7494
- this.intentsByName[name] = fns.map((fn) => new IntentHandler(name, fn));
7455
+ const fns = handlers[name];
7456
+ this.intentsByName[name] = Array.isArray(fns) ? fns : [fns];
7495
7457
  }
7496
7458
  }
7497
7459
  // Innermost scope first, then outward. Concatenated rather than first-match, so a
@@ -7521,14 +7483,12 @@ var ComponentStack = class _ComponentStack {
7521
7483
  }
7522
7484
  };
7523
7485
  var ProvideInfo = class {
7524
- constructor(name, val) {
7525
- this.name = name;
7486
+ constructor(val) {
7526
7487
  this.val = val;
7527
7488
  }
7528
7489
  };
7529
7490
  var LookupInfo = class {
7530
- constructor(name, val) {
7531
- this.name = name;
7491
+ constructor(val) {
7532
7492
  this.val = val;
7533
7493
  }
7534
7494
  };
@@ -7576,13 +7536,13 @@ var Component = class {
7576
7536
  continue;
7577
7537
  }
7578
7538
  const val = parseProvide(this._rawProvide[key], ctx);
7579
- if (val) this.provide[key] = new ProvideInfo(key, val);
7539
+ if (val) this.provide[key] = new ProvideInfo(val);
7580
7540
  }
7581
7541
  for (const entry of this._rawLookup) {
7582
7542
  const name = isString(entry) ? entry : isString(entry?.name) ? entry.name : null;
7583
7543
  if (name === null) continue;
7584
7544
  const defStr = isString(entry?.default) ? entry.default : null;
7585
- this.lookup[name] = new LookupInfo(name, defStr === null ? null : parseField(defStr, ctx));
7545
+ this.lookup[name] = new LookupInfo(defStr === null ? null : parseField(defStr, ctx));
7586
7546
  }
7587
7547
  for (const key in this.lookup)
7588
7548
  if (this.provide[key] !== void 0)
@@ -10405,10 +10365,10 @@ var ATTR_VAL_CHECKERS = {
10405
10365
  }
10406
10366
  };
10407
10367
  function checkConsistentAttrVal(lx, val, env, skipNameVal = false, errCtx = null, isRoot = true) {
10408
- const check3 = ATTR_VAL_CHECKERS[val?.constructor.name];
10409
- if (check3 === void 0) return;
10368
+ const check2 = ATTR_VAL_CHECKERS[val?.constructor.name];
10369
+ if (check2 === void 0) return;
10410
10370
  const recurse = (sub) => checkConsistentAttrVal(lx, sub, env, skipNameVal, errCtx, false);
10411
- check3({ lx, val, env, errCtx, skipNameVal, recurse, isRoot });
10371
+ check2({ lx, val, env, errCtx, skipNameVal, recurse, isRoot });
10412
10372
  }
10413
10373
  var NODE_KIND_TO_CTX = {
10414
10374
  RenderTextNode: { originAttr: "<x text>" },
@@ -10854,34 +10814,16 @@ function dispatchPhase(dispatcher, targetPath, phase, self) {
10854
10814
  // src/oo.js
10855
10815
  var BAD_VALUE2 = /* @__PURE__ */ Symbol("BadValue");
10856
10816
  var nullCoercer = (v) => v;
10857
- function defaultToData(v) {
10858
- if (v instanceof Map) return [...v.entries()];
10859
- if (v instanceof Set) return [...v.values()];
10860
- return v;
10861
- }
10862
10817
  var Field = class {
10863
10818
  constructor(type3, name, typeCheck, coercer, defaultValue = null) {
10864
10819
  this.type = type3;
10865
10820
  this.name = name;
10866
10821
  this.typeCheck = typeCheck;
10867
10822
  this.coercer = coercer;
10868
- this.checks = [];
10869
10823
  this.defaultValue = defaultValue;
10870
10824
  }
10871
- toDataDef() {
10872
- return { type: this.type, defaultValue: defaultToData(this.defaultValue) };
10873
- }
10874
- getFirstFailingCheck(v) {
10875
- if (!this.typeCheck.isValid(v)) return this.typeCheck;
10876
- for (const check3 of this.checks) if (!check3.isValid(v)) return check3;
10877
- return null;
10878
- }
10879
10825
  isValid(v) {
10880
- return this.getFirstFailingCheck(v) === null;
10881
- }
10882
- addCheck(check3) {
10883
- this.checks.push(check3);
10884
- return this;
10826
+ return this.typeCheck(v);
10885
10827
  }
10886
10828
  coerceOr(v, defaultValue = null) {
10887
10829
  if (this.isValid(v)) return v;
@@ -10892,135 +10834,79 @@ var Field = class {
10892
10834
  return this.coerceOr(v, this.defaultValue);
10893
10835
  }
10894
10836
  };
10895
- var Check = class {
10896
- isValid(_v) {
10897
- return true;
10898
- }
10899
- getMessage(_v) {
10900
- return "Invalid";
10901
- }
10902
- };
10903
- var CheckTypeAny = class extends Check {
10904
- };
10905
- var CHECK_TYPE_ANY = new CheckTypeAny();
10906
- var FnCheck = class extends Check {
10907
- constructor(isValidFn, getMessageFn) {
10908
- super();
10909
- this._isValid = isValidFn;
10910
- this._getMessage = getMessageFn;
10911
- }
10912
- isValid(v) {
10913
- return this._isValid(v);
10914
- }
10915
- getMessage(v) {
10916
- return this._getMessage(v);
10917
- }
10837
+ var CHECK_TYPE_ANY = (_v) => true;
10838
+ var CHECK_TYPE_INT = Number.isInteger;
10839
+ var CHECK_TYPE_FLOAT = Number.isFinite;
10840
+ var CHECK_TYPE_BOOL = (v) => typeof v === "boolean";
10841
+ var CHECK_TYPE_STRING = (v) => typeof v === "string";
10842
+ var CHECK_TYPE_LIST = Array.isArray;
10843
+ var CHECK_TYPE_OBJECT = isPlainObject;
10844
+ var CHECK_TYPE_MAP = (v) => v instanceof Map;
10845
+ var CHECK_TYPE_SET = (v) => v instanceof Set;
10846
+ var COERCE_NONE = (_v) => null;
10847
+ var COERCE_BOOL = (v) => !!v;
10848
+ var COERCE_STRING = (v) => v?.toString?.() ?? "";
10849
+ var COERCE_INT = (v) => Number.isFinite(v) ? Math.trunc(v) : null;
10850
+ var COERCE_LIST = (v) => Array.isArray(v) ? [...v] : null;
10851
+ var COERCE_OBJECT = (v) => isPlainObject(v) ? { ...v } : null;
10852
+ var COERCE_MAP = (v) => {
10853
+ if (v instanceof Map) return new Map(v);
10854
+ if (Array.isArray(v) || isPlainObject(v))
10855
+ return new Map(Array.isArray(v) ? v : Object.entries(v));
10856
+ return null;
10918
10857
  };
10919
- var check = (fn, message) => new FnCheck(fn, () => message);
10920
- var CHECK_TYPE_INT = check(Number.isInteger, "Integer expected");
10921
- var CHECK_TYPE_FLOAT = check(Number.isFinite, "Float expected");
10922
- var CHECK_TYPE_BOOL = check((v) => typeof v === "boolean", "Boolean expected");
10923
- var CHECK_TYPE_STRING = check((v) => typeof v === "string", "String expected");
10924
- var CHECK_TYPE_LIST = check(Array.isArray, "Array expected");
10925
- var CHECK_TYPE_OBJECT = check(isPlainObject, "Plain object expected");
10926
- var CHECK_TYPE_MAP = check((v) => v instanceof Map, "Map expected");
10927
- var CHECK_TYPE_SET = check((v) => v instanceof Set, "Set expected");
10858
+ var COERCE_SET = (v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null;
10928
10859
  var FieldBool = class extends Field {
10929
10860
  constructor(name, defaultValue = false) {
10930
- super("bool", name, CHECK_TYPE_BOOL, (v) => !!v, defaultValue);
10861
+ super("bool", name, CHECK_TYPE_BOOL, COERCE_BOOL, defaultValue);
10931
10862
  }
10932
10863
  };
10933
10864
  var FieldAny = class extends Field {
10934
10865
  constructor(name, defaultValue = null) {
10935
10866
  super("any", name, CHECK_TYPE_ANY, nullCoercer, defaultValue);
10936
10867
  }
10937
- toDataDef() {
10938
- return { type: getTypeName(this.defaultValue) ?? "any", defaultValue: this.defaultValue };
10939
- }
10940
10868
  };
10941
10869
  var FieldString = class extends Field {
10942
10870
  constructor(name, defaultValue = "") {
10943
- super("text", name, CHECK_TYPE_STRING, (v) => v?.toString?.() ?? "", defaultValue);
10871
+ super("text", name, CHECK_TYPE_STRING, COERCE_STRING, defaultValue);
10944
10872
  }
10945
10873
  };
10946
10874
  var FieldInt = class extends Field {
10947
10875
  constructor(name, defaultValue = 0) {
10948
- super(
10949
- "int",
10950
- name,
10951
- CHECK_TYPE_INT,
10952
- (v) => Number.isFinite(v) ? Math.trunc(v) : null,
10953
- defaultValue
10954
- );
10876
+ super("int", name, CHECK_TYPE_INT, COERCE_INT, defaultValue);
10955
10877
  }
10956
10878
  };
10957
10879
  var FieldFloat = class extends Field {
10958
10880
  constructor(name, defaultValue = 0) {
10959
- super("float", name, CHECK_TYPE_FLOAT, (_) => null, defaultValue);
10960
- }
10961
- };
10962
- var getTypeName = (v) => v?.constructor?.[COMPONENT]?.name ?? v?.constructor?.getMetaClass?.()?.name ?? null;
10963
- var CheckTypeName = class {
10964
- constructor(typeName) {
10965
- this.typeName = typeName;
10966
- }
10967
- isValid(v) {
10968
- return getTypeName(v) === this.typeName;
10969
- }
10970
- getMessage(v) {
10971
- return `Expected "${this.typeName}", got "${getTypeName(v)}"`;
10881
+ super("float", name, CHECK_TYPE_FLOAT, COERCE_NONE, defaultValue);
10972
10882
  }
10973
10883
  };
10884
+ var metaOf = (v) => v?.constructor?.[COMPONENT] ?? v?.constructor?.getMetaClass?.();
10885
+ var getTypeName = (v) => metaOf(v)?.name ?? null;
10974
10886
  var FieldComp = class extends Field {
10975
10887
  constructor(type3, name, args) {
10976
- super(type3, name, new CheckTypeName(type3), nullCoercer, null);
10888
+ super(type3, name, (v) => getTypeName(v) === type3, nullCoercer, null);
10977
10889
  this.args = args;
10978
10890
  }
10979
- toDataDef() {
10980
- return { component: this.type, args: this.args };
10981
- }
10982
10891
  };
10983
10892
  var FieldList = class extends Field {
10984
10893
  constructor(name, defaultValue = []) {
10985
- super("list", name, CHECK_TYPE_LIST, (v) => Array.isArray(v) ? [...v] : null, defaultValue);
10894
+ super("list", name, CHECK_TYPE_LIST, COERCE_LIST, defaultValue);
10986
10895
  }
10987
10896
  };
10988
10897
  var FieldObject = class extends Field {
10989
10898
  constructor(name, defaultValue = {}) {
10990
- super(
10991
- "object",
10992
- name,
10993
- CHECK_TYPE_OBJECT,
10994
- (v) => isPlainObject(v) ? { ...v } : null,
10995
- defaultValue
10996
- );
10899
+ super("object", name, CHECK_TYPE_OBJECT, COERCE_OBJECT, defaultValue);
10997
10900
  }
10998
10901
  };
10999
10902
  var FieldMap = class extends Field {
11000
10903
  constructor(name, defaultValue = /* @__PURE__ */ new Map()) {
11001
- super(
11002
- "map",
11003
- name,
11004
- CHECK_TYPE_MAP,
11005
- (v) => {
11006
- if (v instanceof Map) return new Map(v);
11007
- if (Array.isArray(v) || isPlainObject(v))
11008
- return new Map(Array.isArray(v) ? v : Object.entries(v));
11009
- return null;
11010
- },
11011
- defaultValue
11012
- );
10904
+ super("map", name, CHECK_TYPE_MAP, COERCE_MAP, defaultValue);
11013
10905
  }
11014
10906
  };
11015
10907
  var FieldSet = class extends Field {
11016
10908
  constructor(name, defaultValue = /* @__PURE__ */ new Set()) {
11017
- super(
11018
- "set",
11019
- name,
11020
- CHECK_TYPE_SET,
11021
- (v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null,
11022
- defaultValue
11023
- );
10909
+ super("set", name, CHECK_TYPE_SET, COERCE_SET, defaultValue);
11024
10910
  }
11025
10911
  };
11026
10912
  function mkCompField(field, scope, args) {
@@ -11118,8 +11004,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
11118
11004
  const value = fields[field];
11119
11005
  const type3 = typeof value;
11120
11006
  if (type3 === "string") b.addField(field, value, FieldString);
11121
- else if (type3 === "number")
11122
- b.addField(field, value, Number.isInteger(value) ? FieldInt : FieldFloat);
11007
+ else if (type3 === "number") b.addField(field, value, FieldFloat);
11123
11008
  else if (type3 === "boolean") b.addField(field, value, FieldBool);
11124
11009
  else if (Array.isArray(value)) b.addField(field, [...value], FieldList);
11125
11010
  else if (value instanceof Set) b.addField(field, new Set(value), FieldSet);
@@ -11140,7 +11025,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
11140
11025
  return b.build();
11141
11026
  }
11142
11027
  function validateDraftFields(current2, draft) {
11143
- const meta = current2?.constructor?.[COMPONENT] ?? current2?.constructor?.getMetaClass?.();
11028
+ const meta = metaOf(current2);
11144
11029
  if (!meta) return;
11145
11030
  for (const [name, field] of Object.entries(meta.fields)) {
11146
11031
  const value = draft[name];
@@ -11199,7 +11084,7 @@ var component = (opts) => Component.fromSpec(opts);
11199
11084
  // src/stack.js
11200
11085
  var STOP = /* @__PURE__ */ Symbol("STOP");
11201
11086
  var NEXT = /* @__PURE__ */ Symbol("NEXT");
11202
- var DEFAULT_LOOKUP_ROUTE = ["dyn", "lex"];
11087
+ var DEFAULT_ROUTE = ["dyn", "lex"];
11203
11088
  function routeLookup(route, lex, dyn) {
11204
11089
  for (let i = 0; i < route.length; i++) {
11205
11090
  const leg = route[i];
@@ -11321,20 +11206,6 @@ var Stack = class _Stack {
11321
11206
  lookupBind(name) {
11322
11207
  return lookup(this.binds, name);
11323
11208
  }
11324
- // The `lex` leg: what a name means in the registration scope of the component being
11325
- // rendered. The scope chain holds components, so this leg only ever answers for a
11326
- // type name — for a value name it is a miss, which is why one default route serves
11327
- // both. Guarded: a non-component `it` has no scope to ask.
11328
- _lookupLex(name) {
11329
- return this.comps.getCompFor(this.it)?.scope.lookupComponent(name) ?? null;
11330
- }
11331
- lookupRouted(name, route = DEFAULT_LOOKUP_ROUTE) {
11332
- return routeLookup(
11333
- route,
11334
- () => this._lookupLex(name),
11335
- () => this.lookupDynamic(name)
11336
- );
11337
- }
11338
11209
  lookupFieldRaw(name) {
11339
11210
  return this.it[name] ?? null;
11340
11211
  }
@@ -11435,28 +11306,46 @@ var Transactor = class {
11435
11306
  if (i !== -1) this._refusalObservers.splice(i, 1);
11436
11307
  };
11437
11308
  }
11438
- // Build and dispatch the observer record for a settled transaction. The
11439
- // resolved handler (`_resolvedHandler`/`_matched`) and per-leaf before/after
11440
- // (`_before`/`_after`) were captured while the handler ran (see callHandler /
11441
- // Transaction.run). No-op when nobody is observing.
11309
+ // Build and dispatch one observer record. Pins field-resolved keys (e.g. a
11310
+ // `.a[.selId]` render target reconstructed from a DOM event) against the root the
11311
+ // handler read, so pathKeys carries concrete keys instead of dropping the dynamic
11312
+ // step. No-op when nobody is observing.
11313
+ _emitRecord(root, { kind, name, args, path, targetPath, handler, handlerName, matched, before, after, parent }) {
11314
+ if (this._observers.length === 0) return;
11315
+ const pinned = path.pinKeys(root);
11316
+ this._emit({
11317
+ kind,
11318
+ name,
11319
+ args: args ?? null,
11320
+ path: pinned,
11321
+ pathKeys: pinned.toKeys(),
11322
+ targetPath,
11323
+ handler: handler ?? null,
11324
+ handlerName: handlerName ?? (handler?.name || null),
11325
+ matched: matched ?? null,
11326
+ before,
11327
+ after,
11328
+ parent,
11329
+ timestamp: Date.now()
11330
+ });
11331
+ }
11332
+ // The observer record for a settled transaction. The resolved handler
11333
+ // (`_resolvedHandler`/`_matched`) and per-leaf before/after (`_before`/`_after`)
11334
+ // were captured while the handler ran (see callHandler / Transaction.run).
11442
11335
  _emitTransaction(transaction, root) {
11443
11336
  if (this._observers.length === 0) return;
11444
11337
  if (transaction._resolvedHandler === void 0) return;
11445
- const path = transaction.getTransactionPath().pinKeys(root);
11446
- this._emit({
11338
+ this._emitRecord(root, {
11447
11339
  kind: transaction.observeKind,
11448
11340
  name: transaction.observeName,
11449
- args: transaction.args ?? null,
11450
- path,
11451
- pathKeys: path.toKeys(),
11341
+ args: transaction.args,
11342
+ path: transaction.getTransactionPath(),
11452
11343
  targetPath: transaction.targetPath ?? transaction.path,
11453
- handler: transaction._resolvedHandler ?? null,
11454
- handlerName: transaction._resolvedHandler?.name || null,
11455
- matched: transaction._matched ?? null,
11344
+ handler: transaction._resolvedHandler,
11345
+ matched: transaction._matched,
11456
11346
  before: transaction._before,
11457
11347
  after: transaction._after,
11458
- parent: transaction.parentTransaction,
11459
- timestamp: Date.now()
11348
+ parent: transaction.parentTransaction
11460
11349
  });
11461
11350
  }
11462
11351
  // Make `child` a tracked unit of `parent`'s subtree: the parent's completion stays open
@@ -11554,7 +11443,7 @@ var Transaction = class {
11554
11443
  // rather than throwing, so a stray call from the wrong place is a message and not a
11555
11444
  // crash. `walk` is undefined here, which is how ctx.reply/ctx.fail tell the two apart.
11556
11445
  stop() {
11557
- console.warn('ctx.stop() is only meaningful in an "intent" handler - ignored');
11446
+ warnNotIntent("stop");
11558
11447
  }
11559
11448
  forward(_opts) {
11560
11449
  console.warn('ctx.forward() needs a "receive" or "intent" handler - ignored');
@@ -11639,11 +11528,8 @@ var InputEvent = class extends Transaction {
11639
11528
  }
11640
11529
  this.transactor.pushIntent(this.dispatchPath, name, args, rest, this);
11641
11530
  }
11642
- buildStack(root, comps) {
11643
- return this.path.toTransactionPath().buildStack(Stack.root(comps, root, this));
11644
- }
11645
11531
  getHandlerAndArgs(root, _instance, comps) {
11646
- const stack = this.buildStack(root, comps);
11532
+ const stack = this.path.toTransactionPath().buildStack(Stack.root(comps, root, this));
11647
11533
  const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
11648
11534
  this._handlerArgs = [...args];
11649
11535
  const path = this.dispatchPath;
@@ -11745,7 +11631,6 @@ var IntentEvent = class extends NameArgsTransaction {
11745
11631
  };
11746
11632
  var PASS = /* @__PURE__ */ Symbol.for("tutuca.intent.pass");
11747
11633
  var REFUSAL_RING_CAP = 200;
11748
- var DEFAULT_ROUTE = ["dyn", "lex"];
11749
11634
  var INTENT_DEPTH = 64;
11750
11635
  var IntentWalk = class {
11751
11636
  constructor(transactor, path, name, args, opts, parent, release) {
@@ -11794,24 +11679,19 @@ var IntentWalk = class {
11794
11679
  const txnPath = this.origin.toTransactionPath();
11795
11680
  const leaf = txnPath.lookup(root);
11796
11681
  const chain = this.transactor.comps.getIntentChainFor(leaf, this.name);
11797
- if (this.transactor._observers.length > 0) {
11798
- const path = txnPath.pinKeys(root);
11799
- this.transactor._emit({
11800
- kind: "intent",
11801
- name: this.name,
11802
- args: this.args,
11803
- path,
11804
- pathKeys: path.toKeys(),
11805
- targetPath: this.origin,
11806
- handler: chain[0]?.fn ?? null,
11807
- handlerName: chain[0]?.fn?.name || this.name,
11808
- matched: chain.length > 0 ? "exact" : "none",
11809
- before: leaf,
11810
- after: void 0,
11811
- parent: this.parent,
11812
- timestamp: Date.now()
11813
- });
11814
- }
11682
+ this.transactor._emitRecord(root, {
11683
+ kind: "intent",
11684
+ name: this.name,
11685
+ args: this.args,
11686
+ path: txnPath,
11687
+ targetPath: this.origin,
11688
+ handler: chain[0],
11689
+ handlerName: chain[0]?.name || this.name,
11690
+ matched: chain.length > 0 ? "exact" : "none",
11691
+ before: leaf,
11692
+ after: void 0,
11693
+ parent: this.parent
11694
+ });
11815
11695
  if (chain.length === 0) return this.advance();
11816
11696
  const p = this._runLex(chain, 0);
11817
11697
  this.transactor._inflight.add(p);
@@ -11822,7 +11702,7 @@ var IntentWalk = class {
11822
11702
  if (i >= chain.length) return this.advance();
11823
11703
  const ctx = new Dispatcher(this.origin, this.transactor, this.parent);
11824
11704
  try {
11825
- const res = await chain[i].fn.apply(null, [...this.args, ctx]);
11705
+ const res = await chain[i].apply(null, [...this.args, ctx]);
11826
11706
  if (res === PASS) return this._runLex(chain, i + 1);
11827
11707
  this.answer("Ok", res);
11828
11708
  } catch (error) {
@@ -11975,9 +11855,8 @@ var Dispatcher = class {
11975
11855
  // the same spelling as `ctx.intent` — `["dyn"]` the render ancestry, `["lex"]` the
11976
11856
  // registration scope, default both.
11977
11857
  lookup(name, opts) {
11978
- const route = opts?.route ?? DEFAULT_LOOKUP_ROUTE;
11979
11858
  return routeLookup(
11980
- route,
11859
+ opts?.route ?? DEFAULT_ROUTE,
11981
11860
  () => this._lookupLex(name),
11982
11861
  () => this._stack()?.lookupDynamic(name) ?? null
11983
11862
  );
@@ -11996,12 +11875,10 @@ var Dispatcher = class {
11996
11875
  // can only ever answer with one; the `dyn` leg reads a binding an ancestor
11997
11876
  // published, so it is the leg that has to be checked.
11998
11877
  lookupType(name, opts) {
11999
- const v = this.lookup(name, opts);
11878
+ const route = opts?.route ?? DEFAULT_ROUTE;
11879
+ const v = this.lookup(name, { route });
12000
11880
  if (v == null) {
12001
- this.transactor.refuse("TYPE_NOT_FOUND", {
12002
- name,
12003
- route: opts?.route ?? DEFAULT_LOOKUP_ROUTE
12004
- });
11881
+ this.transactor.refuse("TYPE_NOT_FOUND", { name, route });
12005
11882
  return null;
12006
11883
  }
12007
11884
  if (v?.[COMPONENT] == null) {
@@ -12803,7 +12680,14 @@ var App = class {
12803
12680
  const { type: type3 } = e;
12804
12681
  const isDrag = type3 === "dragover" || type3 === "dragstart" || type3 === "dragend" || type3 === "drop";
12805
12682
  const { rootNode: root, maxEventNodeDepth: maxDepth, comps, transactor } = this;
12806
- const [path, handlers] = Path.fromEvent(e, root, maxDepth, comps, !isDrag);
12683
+ const [path, handlers] = Path.fromNodeAndEventName(
12684
+ e.target,
12685
+ type3,
12686
+ root,
12687
+ maxDepth,
12688
+ comps,
12689
+ !isDrag
12690
+ );
12807
12691
  if (isDrag) this._handleDragEvent(e, type3, path);
12808
12692
  if (path !== null && handlers !== null)
12809
12693
  for (const handler of handlers) transactor.transactInputNow(path, e, handler, this.dragInfo);
@@ -12865,7 +12749,7 @@ var App = class {
12865
12749
  const value = txnPath.lookup(rootValue);
12866
12750
  const dragType = e.target.dataset.dragtype ?? "?";
12867
12751
  const stack = path.toTransactionPath().buildStack(this.makeStack(rootValue));
12868
- this.dragInfo = new DragInfo(txnPath, stack, e, value, dragType, e.target);
12752
+ this.dragInfo = new DragInfo(stack, value, dragType, e.target);
12869
12753
  } else if (type3 === "drop") {
12870
12754
  e.preventDefault();
12871
12755
  this._cleanDragOverAttrs();
@@ -13002,10 +12886,8 @@ function getClosestDropTarget(target, rootNode, count) {
13002
12886
  return null;
13003
12887
  }
13004
12888
  var DragInfo = class {
13005
- constructor(path, stack, e, val, type3, node) {
13006
- this.path = path;
12889
+ constructor(stack, val, type3, node) {
13007
12890
  this.stack = stack;
13008
- this.e = e;
13009
12891
  this.val = val;
13010
12892
  this.type = type3;
13011
12893
  this.node = node;
@@ -13097,6 +12979,8 @@ var Renderer = class {
13097
12979
  setNullCache() {
13098
12980
  this.cache = new NullDomCache();
13099
12981
  }
12982
+ // Library utilities for consumers embedding tutuca: render a value to a detached
12983
+ // DOM node / an HTML string. Not called by the framework itself.
13100
12984
  renderToDOM(stack, val) {
13101
12985
  const rootNode = document.createElement("div");
13102
12986
  const rOpts = { document };
@@ -13314,7 +13198,7 @@ function shadowCheckComponent(Comp) {
13314
13198
  });
13315
13199
  return checkComponent(shadowComp).reports;
13316
13200
  }
13317
- function check2(app) {
13201
+ function check(app) {
13318
13202
  const counts = { error: 0, warn: 0, hint: 0 };
13319
13203
  for (const Comp of app.comps.byId.values()) {
13320
13204
  const reports = shadowCheckComponent(Comp);
@@ -13438,7 +13322,7 @@ export {
13438
13322
  UNKNOWN_X_OP,
13439
13323
  UNSUPPORTED_EXPR_SYNTAX,
13440
13324
  X_OP_IGNORES_CHILDREN,
13441
- check2 as check,
13325
+ check,
13442
13326
  checkComponent,
13443
13327
  collectIterBindings,
13444
13328
  compileClassesToStyle,