tutuca 0.9.14 → 0.9.16

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.
@@ -112,9 +112,8 @@ class Path {
112
112
  let curVal = v;
113
113
  for (const step of this.steps) {
114
114
  curVal = step.lookup(curVal, NONE);
115
- if (curVal === NONE) {
115
+ if (curVal === NONE)
116
116
  return dval;
117
- }
118
117
  }
119
118
  return curVal;
120
119
  }
@@ -124,9 +123,8 @@ class Path {
124
123
  for (let i = 0;i < this.steps.length; i++) {
125
124
  intermediates[i] = curVal;
126
125
  curVal = this.steps[i].lookup(curVal, NONE);
127
- if (curVal === NONE) {
126
+ if (curVal === NONE)
128
127
  return root;
129
- }
130
128
  }
131
129
  let newVal = v;
132
130
  for (let i = this.steps.length - 1;i >= 0; i--) {
@@ -144,7 +142,7 @@ class Path {
144
142
  console.warn(`bad PathItem`, { root, curVal, step, path: this });
145
143
  return null;
146
144
  }
147
- step.updateBindings(curVal, stack.binds.head.bindings);
145
+ step.updateBindings(curVal, stack.binds[0].bindings);
148
146
  stack = stack.enter(curVal, {}, step.isFrame);
149
147
  }
150
148
  return stack;
@@ -193,9 +191,8 @@ var EMPTY_META = {};
193
191
  function parseMetaComment(n) {
194
192
  if (n?.nodeType === 8 && n.textContent[0] === "§") {
195
193
  const m = parseMetaComment(n.previousSibling);
196
- if (m !== EMPTY_META) {
194
+ if (m !== EMPTY_META)
197
195
  return m;
198
- }
199
196
  try {
200
197
  return JSON.parse(n.textContent.slice(1, -1));
201
198
  } catch (err) {
@@ -218,9 +215,8 @@ function resolvePathStep(comp, nodeIds, vid) {
218
215
  const j = node.pathInNext ? i + 1 : i;
219
216
  const { si, sk, nid: nodeId } = nodeIds[j];
220
217
  const pi = node.pathInNext ? comp.getNodeForId(+nodeId, vid).val.toPathItem() : node.toPathItem();
221
- if (pi !== null) {
218
+ if (pi !== null)
222
219
  return si !== undefined ? pi.withIndex(+si) : sk ? pi.withKey(sk) : pi;
223
- }
224
220
  }
225
221
  return null;
226
222
  }
@@ -270,20 +266,12 @@ class ValParser {
270
266
  }
271
267
  allowFieldOnly() {
272
268
  this.okField = true;
273
- this.okBind = false;
274
- this.okComputed = false;
275
- this.okDyn = false;
276
- this.okType = false;
277
- this.okRequest = false;
278
- this.okName = false;
279
- this.okConst = false;
280
- this.okStrTpl = false;
281
- this.okSeqAccess = false;
269
+ this.okBind = this.okComputed = this.okDyn = this.okType = this.okRequest = false;
270
+ this.okName = this.okConst = this.okStrTpl = this.okSeqAccess = false;
282
271
  }
283
272
  _parseSeqAccess(s, px) {
284
- if (!this.okSeqAccess) {
273
+ if (!this.okSeqAccess)
285
274
  return null;
286
- }
287
275
  const openSquareBracketIndex = s.indexOf("[");
288
276
  this.allowFieldOnly();
289
277
  const left = this.parse(s.slice(0, openSquareBracketIndex), px);
@@ -326,15 +314,14 @@ class ValParser {
326
314
  return this.okRequest ? parseReq(s.slice(1), px) : null;
327
315
  }
328
316
  const num = VALID_FLOAT_RE.test(s) ? parseFloat(s) : null;
329
- if (Number.isFinite(num)) {
317
+ if (Number.isFinite(num))
330
318
  return this.okConst ? parseConst(num, px) : null;
331
- } else if (s === "true" || s === "false") {
319
+ else if (s === "true" || s === "false")
332
320
  return this.okConst ? parseConst(s === "true", px) : null;
333
- } else if (charCode >= 97 && charCode <= 122) {
321
+ else if (charCode >= 97 && charCode <= 122)
334
322
  return this.okName ? parseName(s, px) : null;
335
- } else if (charCode >= 65 && charCode <= 90) {
323
+ else if (charCode >= 65 && charCode <= 90)
336
324
  return this.okType ? parseType(s, px) : null;
337
- }
338
325
  return null;
339
326
  }
340
327
  parseDynamic(s, px) {
@@ -344,19 +331,13 @@ class ValParser {
344
331
  }
345
332
  parseEach(s, px) {
346
333
  this.allowFieldOnly();
347
- this.okComputed = true;
348
- this.okDyn = true;
334
+ this.okComputed = this.okDyn = true;
349
335
  return this.parse(s, px);
350
336
  }
351
337
  allowHandlerArg() {
352
338
  this.allowFieldOnly();
353
- this.okBind = true;
354
- this.okComputed = true;
355
- this.okDyn = true;
356
- this.okType = true;
357
- this.okRequest = true;
358
- this.okName = true;
359
- this.okConst = true;
339
+ this.okBind = this.okComputed = this.okDyn = this.okType = this.okRequest = true;
340
+ this.okName = this.okConst = true;
360
341
  }
361
342
  parseHandlerArg(s, px) {
362
343
  this.allowHandlerArg();
@@ -379,25 +360,17 @@ class ValParser {
379
360
  }
380
361
  parseAll(s, px) {
381
362
  this.allowHandlerArg();
382
- this.okStrTpl = true;
383
- this.okSeqAccess = true;
363
+ this.okStrTpl = this.okSeqAccess = true;
384
364
  return this.parse(s, px);
385
365
  }
386
366
  parseCondValue(s, px) {
387
367
  this.allowFieldOnly();
388
- this.okBind = true;
389
- this.okComputed = true;
390
- this.okDyn = true;
391
- this.okConst = true;
368
+ this.okBind = this.okComputed = this.okDyn = this.okConst = true;
392
369
  return this.parse(s, px);
393
370
  }
394
371
  parseText(s, px) {
395
372
  this.allowFieldOnly();
396
- this.okBind = true;
397
- this.okComputed = true;
398
- this.okDyn = true;
399
- this.okConst = true;
400
- this.okStrTpl = true;
373
+ this.okBind = this.okComputed = this.okDyn = this.okConst = this.okStrTpl = true;
401
374
  return this.parse(s, px);
402
375
  }
403
376
  parseRender(s, px) {
@@ -445,9 +418,8 @@ class StrTplVal extends VarVal {
445
418
  }
446
419
  eval(stack) {
447
420
  const strs = new Array(this.vals.length);
448
- for (let i = 0;i < this.vals.length; i++) {
421
+ for (let i = 0;i < this.vals.length; i++)
449
422
  strs[i] = this.vals[i]?.eval(stack, "");
450
- }
451
423
  return strs.join("");
452
424
  }
453
425
  static parse(s, px) {
@@ -603,15 +575,13 @@ function getValSubType(s) {
603
575
  for (let i = 0;i < s.length; i++) {
604
576
  switch (s.charCodeAt(i)) {
605
577
  case 91:
606
- if (open > 0) {
578
+ if (open > 0)
607
579
  return VAL_SUB_TYPE_INVALID;
608
- }
609
580
  open += 1;
610
581
  break;
611
582
  case 93:
612
- if (close > 0 || open === 0) {
583
+ if (close > 0 || open === 0)
613
584
  return VAL_SUB_TYPE_INVALID;
614
- }
615
585
  close += 1;
616
586
  break;
617
587
  case 123:
@@ -620,9 +590,8 @@ function getValSubType(s) {
620
590
  return VAL_SUB_TYPE_CONST_STRING;
621
591
  }
622
592
  }
623
- if (open > 0 || close > 0) {
593
+ if (open > 0 || close > 0)
624
594
  return open === 1 && close === 1 ? VAL_SUB_TYPE_SEQ_ACCESS : VAL_SUB_TYPE_INVALID;
625
- }
626
595
  return -1;
627
596
  }
628
597
  var vp = new ValParser;
@@ -683,14 +652,12 @@ class AttrParser {
683
652
  }
684
653
  }
685
654
  parseThen(s) {
686
- if (this.ifAttr) {
655
+ if (this.ifAttr)
687
656
  this.ifAttr.thenVal = vp.parseAttr(s, this.px) ?? NOT_SET_VAL;
688
- }
689
657
  }
690
658
  parseElse(value) {
691
- if (this.ifAttr) {
659
+ if (this.ifAttr)
692
660
  this.ifAttr.elseVal = vp.parseAttr(value, this.px) ?? NOT_SET_VAL;
693
- }
694
661
  }
695
662
  parseEvent(directiveName, value) {
696
663
  const [eventName, ...modifiers] = directiveName.slice(3).split("+");
@@ -749,25 +716,22 @@ class AttrParser {
749
716
  this.parseElse(s);
750
717
  return;
751
718
  }
752
- if (directiveName.startsWith("on.")) {
719
+ if (directiveName.startsWith("on."))
753
720
  this.parseEvent(directiveName, s);
754
- } else if (directiveName.startsWith("if.")) {
721
+ else if (directiveName.startsWith("if."))
755
722
  this.parseIf(directiveName, s);
756
- } else if (directiveName.startsWith("then.")) {
723
+ else if (directiveName.startsWith("then."))
757
724
  this.parseThen(s);
758
- } else if (directiveName.startsWith("else.")) {
725
+ else if (directiveName.startsWith("else."))
759
726
  this.parseElse(s);
760
- }
761
727
  }
762
728
  _parseWhen(s) {
763
- if (this.eachAttr !== null) {
729
+ if (this.eachAttr !== null)
764
730
  this.eachAttr.whenVal = vp.parseAlter(s, this.px);
765
- }
766
731
  }
767
732
  _parseLoopWith(s) {
768
- if (this.eachAttr !== null) {
733
+ if (this.eachAttr !== null)
769
734
  this.eachAttr.loopWithVal = vp.parseAlter(s, this.px);
770
- }
771
735
  }
772
736
  parse(attributes, parseAll = false) {
773
737
  for (const { name, value } of attributes) {
@@ -794,9 +758,8 @@ class ConstAttrs extends Attributes {
794
758
  }
795
759
  static fromAttrs(attrs) {
796
760
  const attrsObj = {};
797
- for (const attr of attrs) {
761
+ for (const attr of attrs)
798
762
  attrsObj[attr.name] = attr.val.eval(null);
799
- }
800
763
  return new ConstAttrs(attrsObj);
801
764
  }
802
765
  setDataAttr(key, val) {
@@ -804,9 +767,8 @@ class ConstAttrs extends Attributes {
804
767
  }
805
768
  toMacroVars() {
806
769
  const r = {};
807
- for (const name in this.items) {
770
+ for (const name in this.items)
808
771
  r[name] = `'${this.items[name]}'`;
809
- }
810
772
  return r;
811
773
  }
812
774
  isConstant() {
@@ -817,7 +779,8 @@ class ConstAttrs extends Attributes {
817
779
  class DynAttrs extends Attributes {
818
780
  eval(stack) {
819
781
  const attrs = {};
820
- for (const attr of this.items) {
782
+ for (let i = 0;i < this.items.length; i++) {
783
+ const attr = this.items[i];
821
784
  attrs[attr.name] = attr.eval(stack);
822
785
  }
823
786
  return attrs;
@@ -827,9 +790,8 @@ class DynAttrs extends Attributes {
827
790
  }
828
791
  toMacroVars() {
829
792
  const r = {};
830
- for (const attr of this.items) {
793
+ for (const attr of this.items)
831
794
  r[attr.name] = attr.val.toString();
832
- }
833
795
  return r;
834
796
  }
835
797
  }
@@ -889,17 +851,15 @@ class EventHandler {
889
851
  }
890
852
  getHandlerAndArgs(stack, _event) {
891
853
  const argValues = new Array(this.args.length);
892
- for (let i = 0;i < argValues.length; i++) {
854
+ for (let i = 0;i < argValues.length; i++)
893
855
  argValues[i] = this.args[i].eval(stack);
894
- }
895
856
  return [this.handlerVal.eval(stack), argValues];
896
857
  }
897
858
  static parse(s, px) {
898
859
  const [handlerName, ...rawArgs] = s.trim().split(/\s+/);
899
860
  const handlerVal = vp.parseHandlerName(handlerName, px);
900
- if (handlerVal === null) {
861
+ if (handlerVal === null)
901
862
  return null;
902
- }
903
863
  const args = new Array(rawArgs.length);
904
864
  vp.allowHandlerArg();
905
865
  for (let i = 0;i < rawArgs.length; i++) {
@@ -924,8 +884,8 @@ class RequestHandler {
924
884
 
925
885
  // src/anode.js
926
886
  class BaseNode {
927
- render(_stack, rx) {
928
- return rx.renderEmpty();
887
+ render(_stack, _rx) {
888
+ return null;
929
889
  }
930
890
  setDataAttr(key, val) {
931
891
  console.warn("setDataAttr not implemented for", this, { key, val });
@@ -941,8 +901,8 @@ class TextNode extends BaseNode {
941
901
  super();
942
902
  this.val = val;
943
903
  }
944
- render(_stack, rx) {
945
- return rx.renderText(this.val);
904
+ render(_stack, _rx) {
905
+ return this.val;
946
906
  }
947
907
  isWhiteSpace() {
948
908
  for (let i = 0;i < this.val.length; i++) {
@@ -1233,8 +1193,8 @@ class RenderEachNode extends RenderViewId {
1233
1193
  }
1234
1194
 
1235
1195
  class RenderTextNode extends ANode {
1236
- render(stack, rx) {
1237
- return rx.renderText(this.val.eval(stack));
1196
+ render(stack, _rx) {
1197
+ return this.val.eval(stack);
1238
1198
  }
1239
1199
  }
1240
1200
 
@@ -1272,13 +1232,13 @@ class WrapperNode extends ANode {
1272
1232
 
1273
1233
  class ShowNode extends WrapperNode {
1274
1234
  render(stack, rx) {
1275
- return this.val.eval(stack) ? this.node.render(stack, rx) : rx.renderEmpty();
1235
+ return this.val.eval(stack) ? this.node.render(stack, rx) : null;
1276
1236
  }
1277
1237
  }
1278
1238
 
1279
1239
  class HideNode extends WrapperNode {
1280
1240
  render(stack, rx) {
1281
- return this.val.eval(stack) ? rx.renderEmpty() : this.node.render(stack, rx);
1241
+ return this.val.eval(stack) ? null : this.node.render(stack, rx);
1282
1242
  }
1283
1243
  }
1284
1244
 
@@ -1451,7 +1411,7 @@ function condenseChildsWhites(childs) {
1451
1411
  }
1452
1412
 
1453
1413
  class View {
1454
- constructor(name, rawView, style = "", anode = null, ctx = null) {
1414
+ constructor(name, rawView = "No View Defined", style = "", anode = null, ctx = null) {
1455
1415
  this.name = name;
1456
1416
  this.anode = anode;
1457
1417
  this.style = style;
@@ -1546,6 +1506,63 @@ function compileModifiers(eventName, names) {
1546
1506
  };
1547
1507
  }
1548
1508
 
1509
+ // src/util/parsectx.js
1510
+ class ParseCtxClassSetCollector extends ParseContext {
1511
+ constructor(...args) {
1512
+ super(...args);
1513
+ this.classes = new Set;
1514
+ }
1515
+ _addClasses(s) {
1516
+ for (const v of s.split(/\s+/)) {
1517
+ this.classes.add(v);
1518
+ }
1519
+ }
1520
+ enterMacro(macroName, macroVars, macroSlots) {
1521
+ const { DOMParser: DP, Text, Comment, nodes, events, macroNodes } = this;
1522
+ const frame = { macroName, macroVars, macroSlots };
1523
+ const v = new ParseCtxClassSetCollector(DP, Text, Comment, nodes, events, macroNodes, frame, this);
1524
+ v.classes = this.classes;
1525
+ return v;
1526
+ }
1527
+ onAttributes(attrs, _wrapperAttrs, _textChild) {
1528
+ if (Array.isArray(attrs.items)) {
1529
+ for (const attr of attrs.items) {
1530
+ if (attr.name !== "class") {
1531
+ continue;
1532
+ }
1533
+ const { val, thenVal, elseVal } = attr;
1534
+ if (thenVal !== undefined) {
1535
+ this._maybeAddVal(thenVal);
1536
+ this._maybeAddVal(elseVal);
1537
+ } else {
1538
+ this._maybeAddVal(val);
1539
+ }
1540
+ }
1541
+ } else {
1542
+ const attr = attrs.items.class;
1543
+ if (attr) {
1544
+ this._addClasses(attr);
1545
+ }
1546
+ }
1547
+ }
1548
+ _maybeAddVal(value) {
1549
+ if (!this._maybeAddStrTpl(value) && typeof value?.val === "string") {
1550
+ this._addClasses(value.val);
1551
+ }
1552
+ }
1553
+ _maybeAddStrTpl(value) {
1554
+ if (value?.vals !== undefined) {
1555
+ for (const val of value.vals) {
1556
+ if (val instanceof ConstVal && val.val !== "") {
1557
+ this._addClasses(val.val);
1558
+ }
1559
+ }
1560
+ return true;
1561
+ }
1562
+ return false;
1563
+ }
1564
+ }
1565
+
1549
1566
  // src/cache.js
1550
1567
  class NullDomCache {
1551
1568
  get(_k, _cacheKey) {}
@@ -1563,11 +1580,10 @@ class WeakMapDomCache {
1563
1580
  this.map = new WeakMap;
1564
1581
  }
1565
1582
  _returnValue(r) {
1566
- if (r === undefined) {
1583
+ if (r === undefined)
1567
1584
  this.miss += 1;
1568
- } else {
1585
+ else
1569
1586
  this.hit += 1;
1570
- }
1571
1587
  return r;
1572
1588
  }
1573
1589
  get(k, cacheKey) {
@@ -1575,13 +1591,12 @@ class WeakMapDomCache {
1575
1591
  }
1576
1592
  set(k, cacheKey, v) {
1577
1593
  const cur = this.map.get(k);
1578
- if (cur) {
1594
+ if (cur)
1579
1595
  cur[cacheKey] = v;
1580
- } else if (typeof k === "object") {
1596
+ else if (typeof k === "object")
1581
1597
  this.map.set(k, { [cacheKey]: v });
1582
- } else {
1598
+ else
1583
1599
  this.badKey += 1;
1584
- }
1585
1600
  }
1586
1601
  get2(k1, k2, cacheKey) {
1587
1602
  return this._returnValue(this.map.get(k1)?.get?.(k2)?.[cacheKey]);
@@ -1590,11 +1605,10 @@ class WeakMapDomCache {
1590
1605
  const cur1 = this.map.get(k1);
1591
1606
  if (cur1) {
1592
1607
  const cur = cur1.get(k2);
1593
- if (cur) {
1608
+ if (cur)
1594
1609
  cur[cacheKey] = v;
1595
- } else {
1610
+ else
1596
1611
  cur1.set(k2, { [cacheKey]: v });
1597
- }
1598
1612
  } else if (typeof k1 === "object" && typeof k2 === "object") {
1599
1613
  const cur = new WeakMap;
1600
1614
  cur.set(k2, { [cacheKey]: v });
@@ -1625,9 +1639,8 @@ class WeakMapComputedCache {
1625
1639
  const cur = this.map.get(v);
1626
1640
  if (cur) {
1627
1641
  const curValue = cur[key];
1628
- if (curValue !== undefined) {
1642
+ if (curValue !== undefined)
1629
1643
  return curValue;
1630
- }
1631
1644
  const newValue2 = fn.call(v) ?? null;
1632
1645
  cur[key] = newValue2;
1633
1646
  return newValue2;
@@ -1675,9 +1688,8 @@ class Components {
1675
1688
  }
1676
1689
  compileStyles() {
1677
1690
  const styles = [];
1678
- for (const comp of this.byId.values()) {
1691
+ for (const comp of this.byId.values())
1679
1692
  styles.push(comp.compileStyle());
1680
- }
1681
1693
  return styles.join(`
1682
1694
  `);
1683
1695
  }
@@ -1701,9 +1713,8 @@ class ComponentStack {
1701
1713
  this.comps.registerComponent(comp);
1702
1714
  this.byName[comp.name] = comp;
1703
1715
  const alias = aliases[comp.name];
1704
- if (alias) {
1716
+ if (alias)
1705
1717
  this.byName[alias] = comp;
1706
- }
1707
1718
  }
1708
1719
  }
1709
1720
  registerMacros(macros) {
@@ -1713,9 +1724,8 @@ class ComponentStack {
1713
1724
  return this.comps.getCompFor(v);
1714
1725
  }
1715
1726
  registerRequestHandlers(handlers) {
1716
- for (const name in handlers) {
1727
+ for (const name in handlers)
1717
1728
  this.reqsByName[name] = new RequestHandler(name, handlers[name]);
1718
- }
1719
1729
  }
1720
1730
  lookupRequest(name) {
1721
1731
  return this.reqsByName[name] ?? this.parent?.lookupRequest(name) ?? null;
@@ -1761,26 +1771,26 @@ var isString = (v) => typeof v === "string";
1761
1771
  var _compId = 0;
1762
1772
 
1763
1773
  class Component {
1764
- constructor(name, Class, view, views = {}, style = "", commonStyle = "", globalStyle = "", computed = {}, input = {}, logic = {}, bubble = {}, response = {}, alter = {}, dynamic = {}, on = {}) {
1774
+ constructor(Class, o) {
1765
1775
  this.id = _compId++;
1766
- this.name = name;
1776
+ this.name = o.name ?? "UnkComp";
1767
1777
  this.Class = Class;
1768
- this.views = { main: new View("main", view, style) };
1769
- this.commonStyle = commonStyle;
1770
- this.globalStyle = globalStyle;
1771
- this.computed = computed;
1772
- this.input = input;
1773
- this.logic = logic;
1774
- this.bubble = bubble;
1775
- this.response = response;
1776
- this.alter = alter;
1777
- this.on = { stackEnter: on?.stackEnter ?? defaultOnStackEnter };
1778
- for (const name2 in views) {
1779
- const v = views[name2];
1780
- const { view: view2, style: style2 } = isString(v) ? { view: v } : v;
1781
- this.views[name2] = new View(name2, view2, style2);
1782
- }
1783
- this._rawDynamic = dynamic;
1778
+ this.views = { main: new View("main", o.view, o.style) };
1779
+ this.commonStyle = o.commonStyle ?? "";
1780
+ this.globalStyle = o.globalStyle ?? "";
1781
+ this.computed = o.computed ?? {};
1782
+ this.input = o.input ?? {};
1783
+ this.logic = o.logic ?? {};
1784
+ this.bubble = o.bubble ?? {};
1785
+ this.response = o.response ?? {};
1786
+ this.alter = o.alter ?? {};
1787
+ this.on = { stackEnter: o.on?.stackEnter ?? defaultOnStackEnter };
1788
+ for (const name in o.views ?? {}) {
1789
+ const v = o.views[name];
1790
+ const { view, style } = isString(v) ? { view: v } : v;
1791
+ this.views[name] = new View(name, view, style);
1792
+ }
1793
+ this._rawDynamic = o.dynamic ?? {};
1784
1794
  this.dynamic = {};
1785
1795
  this.scope = null;
1786
1796
  }
@@ -1798,9 +1808,8 @@ class Component {
1798
1808
  }
1799
1809
  }
1800
1810
  }
1801
- for (const name in this.views) {
1811
+ for (const name in this.views)
1802
1812
  this.views[name].compile(new ParseContext2, this.scope, this.id);
1803
- }
1804
1813
  }
1805
1814
  make(args, opts) {
1806
1815
  return this.Class.make(args, opts);
@@ -1817,14 +1826,12 @@ class Component {
1817
1826
  compileStyle() {
1818
1827
  const { id, commonStyle, globalStyle, views } = this;
1819
1828
  const styles = commonStyle ? [`[data-cid="${id}"]{${commonStyle}}`] : [];
1820
- if (globalStyle !== "") {
1829
+ if (globalStyle !== "")
1821
1830
  styles.push(globalStyle);
1822
- }
1823
1831
  for (const name in views) {
1824
1832
  const { style } = views[name];
1825
- if (style !== "") {
1833
+ if (style !== "")
1826
1834
  styles.push(`[data-cid="${id}"][data-vid="${name}"]{${style}}`);
1827
- }
1828
1835
  }
1829
1836
  return styles.join(`
1830
1837
  `);
@@ -1837,27 +1844,17 @@ function defaultOnStackEnter(stack) {
1837
1844
  // src/stack.js
1838
1845
  var STOP = Symbol("STOP");
1839
1846
  var NEXT = Symbol("NEXT");
1840
-
1841
- class Pair {
1842
- constructor(head, tail) {
1843
- this.head = head;
1844
- this.tail = tail;
1845
- }
1846
- push(v) {
1847
- return new Pair(v, this);
1848
- }
1849
- lookup(v, dv = null) {
1850
- const { tail } = this;
1851
- const r = this.head.lookup(v);
1852
- return r === STOP ? dv : r === NEXT ? tail !== null ? tail.lookup(v, dv) : dv : r;
1853
- }
1854
- *[Symbol.iterator]() {
1855
- let v = this;
1856
- while (v !== null) {
1857
- yield v.head;
1858
- v = v.tail;
1859
- }
1847
+ function lookup(chain, name, dv = null) {
1848
+ let n = chain;
1849
+ while (n !== null) {
1850
+ const r = n[0].lookup(name);
1851
+ if (r === STOP)
1852
+ return dv;
1853
+ if (r !== NEXT)
1854
+ return r;
1855
+ n = n[1];
1860
1856
  }
1857
+ return dv;
1861
1858
  }
1862
1859
 
1863
1860
  class BindFrame {
@@ -1881,56 +1878,64 @@ class ObjectFrame {
1881
1878
  return v === undefined ? NEXT : v;
1882
1879
  }
1883
1880
  }
1881
+ function computeViewsId(views) {
1882
+ let s = "";
1883
+ let n = views;
1884
+ while (n !== null) {
1885
+ s += n[0];
1886
+ n = n[1];
1887
+ }
1888
+ return s === "main" ? "" : s;
1889
+ }
1884
1890
 
1885
1891
  class Stack {
1886
- constructor(comps, it, binds, dynBinds, views, ctx = null) {
1892
+ constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
1887
1893
  this.comps = comps;
1888
1894
  this.it = it;
1889
1895
  this.binds = binds;
1890
1896
  this.dynBinds = dynBinds;
1891
1897
  this.views = views;
1898
+ this.viewsId = viewsId;
1892
1899
  this.ctx = ctx;
1893
- const viewsId = [...views].join("");
1894
- this.viewsId = viewsId === "main" ? "" : viewsId;
1895
1900
  }
1896
1901
  _enrichOnEnter() {
1897
1902
  return this.comps.getOnEnterFor(this.it).call(this.it, this) ?? this;
1898
1903
  }
1899
1904
  upToFrameBinds() {
1900
- const { comps, binds, dynBinds, views, ctx } = this;
1901
- return binds.head.isFrame ? this : new Stack(comps, binds.tail.head.it, binds.tail, dynBinds, views, ctx);
1905
+ const { comps, binds, dynBinds, views, viewsId, ctx } = this;
1906
+ return binds[0].isFrame ? this : new Stack(comps, binds[1][0].it, binds[1], dynBinds, views, viewsId, ctx);
1902
1907
  }
1903
1908
  static root(comps, it, ctx) {
1904
- const binds = new Pair(new BindFrame(it, { it }, true), null);
1905
- const dynBinds = new Pair(new ObjectFrame({}), null);
1906
- const views = new Pair("main", null);
1907
- return new Stack(comps, it, binds, dynBinds, views, ctx)._enrichOnEnter();
1909
+ const binds = [new BindFrame(it, { it }, true), null];
1910
+ const dynBinds = [new ObjectFrame({}), null];
1911
+ const views = ["main", null];
1912
+ return new Stack(comps, it, binds, dynBinds, views, "", ctx)._enrichOnEnter();
1908
1913
  }
1909
1914
  enter(it, bindings = {}, isFrame = true) {
1910
- const { comps, binds, dynBinds, views, ctx } = this;
1911
- const newBinds = binds.push(new BindFrame(it, bindings, isFrame));
1912
- return new Stack(comps, it, newBinds, dynBinds, views, ctx)._enrichOnEnter();
1915
+ const { comps, binds, dynBinds, views, viewsId, ctx } = this;
1916
+ const newBinds = [new BindFrame(it, bindings, isFrame), binds];
1917
+ return new Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx)._enrichOnEnter();
1913
1918
  }
1914
1919
  pushViewName(name) {
1915
1920
  const { comps, it, binds, dynBinds, views, ctx } = this;
1916
- return new Stack(comps, it, binds, dynBinds, views.push(name), ctx);
1921
+ const newViews = [name, views];
1922
+ return new Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
1917
1923
  }
1918
1924
  withDynamicBindings(dynamics) {
1919
1925
  const dynObj = {};
1920
1926
  const comp = this.comps.getCompFor(this.it);
1921
- for (const dynName of dynamics) {
1927
+ for (const dynName of dynamics)
1922
1928
  comp.dynamic[dynName].evalAndBind(this, dynObj);
1923
- }
1924
- const { comps, it, binds, views, ctx } = this;
1925
- const newDynBinds = this.dynBinds.push(new ObjectFrame(dynObj));
1926
- return new Stack(comps, it, binds, newDynBinds, views, ctx);
1929
+ const { comps, it, binds, views, viewsId, ctx } = this;
1930
+ const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
1931
+ return new Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
1927
1932
  }
1928
1933
  lookupDynamic(name) {
1929
1934
  const d = this.comps.getCompFor(this.it)?.dynamic[name];
1930
- return d ? this.dynBinds.lookup(d.getSymbol(this)) ?? d.val.eval(this) : null;
1935
+ return d ? lookup(this.dynBinds, d.getSymbol(this)) ?? d.val.eval(this) : null;
1931
1936
  }
1932
1937
  lookupBind(name) {
1933
- return this.binds.lookup(name);
1938
+ return lookup(this.binds, name);
1934
1939
  }
1935
1940
  lookupType(name) {
1936
1941
  return this.comps.getCompFor(this.it).scope.lookupComponent(name);
@@ -1946,7 +1951,7 @@ class Stack {
1946
1951
  return this.ctx.lookupName(name);
1947
1952
  }
1948
1953
  lookupComputed(name) {
1949
- const node = this.binds.head.isFrame ? this.binds.head : this.binds.tail.head;
1954
+ const node = this.binds[0].isFrame ? this.binds[0] : this.binds[1][0];
1950
1955
  return this.comps.lookupComputed(node.it, name);
1951
1956
  }
1952
1957
  getHandlerFor(name, key) {
@@ -1956,11 +1961,12 @@ class Stack {
1956
1961
  return this.comps.getRequestFor(this.it, name);
1957
1962
  }
1958
1963
  lookupBestView(views, defaultViewName) {
1959
- for (const viewName of this.views) {
1960
- const view = views[viewName];
1961
- if (view !== undefined) {
1964
+ let n = this.views;
1965
+ while (n !== null) {
1966
+ const view = views[n[0]];
1967
+ if (view !== undefined)
1962
1968
  return view;
1963
- }
1969
+ n = n[1];
1964
1970
  }
1965
1971
  return views[defaultViewName];
1966
1972
  }
@@ -1978,9 +1984,8 @@ class State {
1978
1984
  set(val, info) {
1979
1985
  const old = this.val;
1980
1986
  this.val = val;
1981
- for (const sub of this.changeSubs) {
1987
+ for (const sub of this.changeSubs)
1982
1988
  sub({ val, old, info, timestamp: Date.now() });
1983
- }
1984
1989
  }
1985
1990
  update(fn, info) {
1986
1991
  return this.set(fn(this.val), info);
@@ -2027,14 +2032,8 @@ class Transactor {
2027
2032
  return this.transactions.length > 0;
2028
2033
  }
2029
2034
  transactNext() {
2030
- if (this.hasPendingTransactions) {
2035
+ if (this.hasPendingTransactions)
2031
2036
  this.transact(this.transactions.shift());
2032
- }
2033
- }
2034
- transactAll() {
2035
- while (this.hasPendingTransactions) {
2036
- this.transact(this.transactions.shift());
2037
- }
2038
2037
  }
2039
2038
  transact(transaction) {
2040
2039
  const curState = this.state.val;
@@ -2042,9 +2041,8 @@ class Transactor {
2042
2041
  if (newState !== undefined) {
2043
2042
  this.state.set(newState, { transaction });
2044
2043
  transaction.afterTransaction();
2045
- } else {
2044
+ } else
2046
2045
  console.warn("undefined new state", { curState, transaction });
2047
- }
2048
2046
  }
2049
2047
  transactInputNow(path, event, eventHandler, dragInfo) {
2050
2048
  this.transact(new InputEvent(path, event, eventHandler, this, dragInfo));
@@ -2204,9 +2202,8 @@ class LogicEvent extends NameArgsTransaction {
2204
2202
  }
2205
2203
  afterTransaction() {
2206
2204
  const { path, name, args, opts } = this;
2207
- if (opts.bubbles && path.steps.length > 0) {
2205
+ if (opts.bubbles && path.steps.length > 0)
2208
2206
  this.transactor.pushBubble(path.popStep(), name, args, opts, this);
2209
- }
2210
2207
  }
2211
2208
  }
2212
2209
 
@@ -2246,7 +2243,7 @@ class Task {
2246
2243
  }
2247
2244
 
2248
2245
  class Dispatcher {
2249
- constructor(path, transactor, parentTransaction = null) {
2246
+ constructor(path, transactor, parentTransaction) {
2250
2247
  this.path = path;
2251
2248
  this.transactor = transactor;
2252
2249
  this.parent = parentTransaction;
@@ -2296,102 +2293,503 @@ class PathChanges extends PathBuilder {
2296
2293
  }
2297
2294
  }
2298
2295
 
2299
- // src/app.js
2300
- class App {
2301
- constructor(rootNode, renderFn, comps, renderer, ParseContext2) {
2302
- this.rootNode = rootNode;
2303
- this.comps = comps;
2304
- this.compStack = new ComponentStack(comps);
2305
- this.transactor = new Transactor(comps, null);
2306
- this.ParseContext = ParseContext2;
2307
- this.renderer = renderer;
2308
- this.renderFn = renderFn;
2309
- this.maxEventNodeDepth = Infinity;
2310
- this._transactNextBatchId = this._evictCacheId = null;
2311
- this._eventNames = new Set(["dragstart", "dragover", "dragend"]);
2312
- this.dragInfo = this.curDragOver = null;
2313
- this.transactor.onTransactionPushed = (_transaction) => {
2314
- if (this._transactNextBatchId === null) {
2315
- this._scheduleNextTransactionBatchExecution();
2316
- }
2317
- };
2318
- this._compiled = false;
2296
+ // src/vdom.js
2297
+ var isHtmlAttribute = (propName) => propName[4] === "-" && (propName[0] === "d" || propName[0] === "a");
2298
+ var isObject = (v) => v !== null && typeof v === "object";
2299
+ var prototypesDiffer = (a, b) => Object.getPrototypeOf(a) !== Object.getPrototypeOf(b);
2300
+ function applyProperties(node, props, previous) {
2301
+ for (const propName in props) {
2302
+ const propValue = props[propName];
2303
+ if (propValue === undefined)
2304
+ removeProperty(node, propName, previous);
2305
+ else if (isHtmlAttribute(propName))
2306
+ node.setAttribute(propName, propValue);
2307
+ else if (propName === "dangerouslySetInnerHTML")
2308
+ node.innerHTML = propValue.__html ?? "";
2309
+ else if (isObject(propValue))
2310
+ patchObject(node, previous, propName, propValue);
2311
+ else if (propName === "className")
2312
+ node.setAttribute("class", propValue);
2313
+ else
2314
+ node[propName] = propValue;
2319
2315
  }
2320
- get state() {
2321
- return this.transactor.state;
2316
+ }
2317
+ function removeProperty(node, propName, previous) {
2318
+ const previousValue = previous[propName];
2319
+ if (propName === "dangerouslySetInnerHTML")
2320
+ node.replaceChildren();
2321
+ else if (propName === "className")
2322
+ node.removeAttribute("class");
2323
+ else if (propName === "htmlFor")
2324
+ node.removeAttribute("for");
2325
+ else if (typeof previousValue === "string" || isHtmlAttribute(propName))
2326
+ node.removeAttribute(propName);
2327
+ else
2328
+ node[propName] = null;
2329
+ }
2330
+ function patchObject(node, previous, propName, propValue) {
2331
+ const previousValue = previous?.[propName];
2332
+ if (isObject(previousValue) && prototypesDiffer(previousValue, propValue)) {
2333
+ node[propName] = propValue;
2334
+ return;
2322
2335
  }
2323
- handleEvent(e) {
2324
- const isDragStart = e.type === "dragstart";
2325
- const isDragOver = e.type === "dragover";
2326
- const isDragEnd = e.type === "dragend";
2327
- const { rootNode: root, maxEventNodeDepth: maxDepth, comps } = this;
2328
- const stopOnNoEvent = !(isDragOver || isDragStart || isDragEnd);
2329
- const [path, handlers] = Path.fromEvent(e, root, maxDepth, comps, stopOnNoEvent);
2330
- if (isDragOver) {
2331
- const dropTarget = getClosestDropTarget(e.target, this.rootNode, 50);
2332
- if (dropTarget !== null) {
2333
- e.preventDefault();
2334
- this._cleanDragOverAttrs();
2335
- this.curDragOver = dropTarget;
2336
- dropTarget.dataset.draggingover = this.dragInfo.type;
2337
- }
2338
- } else if (isDragStart) {
2339
- e.target.dataset.dragging = 1;
2340
- const rootValue = this.state.val;
2341
- const value = path.lookup(rootValue);
2342
- const type = e.target.dataset.dragtype ?? "?";
2343
- const stack = path.buildStack(this.makeStack(rootValue));
2344
- this.dragInfo = new DragInfo(path, stack, e, value, type, e.target);
2345
- } else if (isDragEnd) {
2346
- delete this.dragInfo.node.dataset.dragging;
2347
- this.dragInfo = null;
2348
- this._cleanDragOverAttrs();
2349
- }
2350
- if (path !== null && handlers !== null) {
2351
- for (const handler of handlers) {
2352
- this.transactor.transactInputNow(path, e, handler, this.dragInfo);
2353
- }
2354
- }
2336
+ if (!isObject(node[propName]))
2337
+ node[propName] = {};
2338
+ const target = node[propName];
2339
+ for (const k in propValue)
2340
+ target[k] = propValue[k];
2341
+ }
2342
+
2343
+ class VBase {
2344
+ }
2345
+ var getKey = (child) => child instanceof VNode ? child.key : undefined;
2346
+ var isIterable = (obj) => obj != null && typeof obj !== "string" && typeof obj[Symbol.iterator] === "function";
2347
+ function childsEqual(a, b) {
2348
+ if (a === b)
2349
+ return true;
2350
+ for (let i = 0;i < a.length; i++)
2351
+ if (!a[i].isEqualTo(b[i]))
2352
+ return false;
2353
+ return true;
2354
+ }
2355
+ function appendChildNodes(parent, childs, opts) {
2356
+ for (const child of childs)
2357
+ parent.appendChild(child.toDom(opts));
2358
+ }
2359
+ function addChild(normalizedChildren, child) {
2360
+ if (child == null)
2361
+ return;
2362
+ if (isIterable(child)) {
2363
+ for (const c of child)
2364
+ addChild(normalizedChildren, c);
2365
+ } else if (child instanceof VBase) {
2366
+ if (child instanceof VFragment)
2367
+ normalizedChildren.push(...child.childs);
2368
+ else
2369
+ normalizedChildren.push(child);
2370
+ } else
2371
+ normalizedChildren.push(new VText(child));
2372
+ }
2373
+
2374
+ class VText extends VBase {
2375
+ constructor(text) {
2376
+ super();
2377
+ this.text = String(text);
2355
2378
  }
2356
- makeStack(rootValue) {
2357
- return Stack.root(this.comps, rootValue);
2379
+ get nodeType() {
2380
+ return 3;
2358
2381
  }
2359
- _cleanDragOverAttrs() {
2360
- if (this.curDragOver !== null) {
2361
- delete this.curDragOver.dataset.draggingover;
2362
- this.curDragOver = null;
2363
- }
2382
+ isEqualTo(other) {
2383
+ return other instanceof VText && this.text === other.text;
2364
2384
  }
2365
- render() {
2366
- const root = this.state.val;
2367
- const stack = this.makeStack(root);
2368
- return this.renderFn(this.renderer.renderRoot(stack, root), this.rootNode);
2385
+ toDom(opts) {
2386
+ return opts.document.createTextNode(this.text);
2369
2387
  }
2370
- onChange(callback) {
2371
- this.transactor.state.onChange(callback);
2388
+ }
2389
+
2390
+ class VComment extends VBase {
2391
+ constructor(text) {
2392
+ super();
2393
+ this.text = text;
2372
2394
  }
2373
- compile() {
2374
- for (const Comp of this.comps.byId.values()) {
2375
- Comp.compile(this.ParseContext);
2376
- for (const key in Comp.views) {
2377
- for (const name of Comp.views[key].ctx.genEventNames()) {
2378
- this._eventNames.add(name);
2379
- }
2380
- }
2381
- }
2382
- this._compiled = true;
2395
+ get nodeType() {
2396
+ return 8;
2383
2397
  }
2384
- start(opts) {
2385
- if (!this._compiled) {
2386
- this.compile();
2398
+ isEqualTo(other) {
2399
+ return other instanceof VComment && this.text === other.text;
2400
+ }
2401
+ toDom(opts) {
2402
+ return opts.document.createComment(this.text);
2403
+ }
2404
+ }
2405
+
2406
+ class VFragment extends VBase {
2407
+ constructor(childs) {
2408
+ super();
2409
+ this.childs = [];
2410
+ addChild(this.childs, childs);
2411
+ }
2412
+ get nodeType() {
2413
+ return 11;
2414
+ }
2415
+ isEqualTo(other) {
2416
+ if (!(other instanceof VFragment) || this.childs.length !== other.childs.length)
2417
+ return false;
2418
+ return childsEqual(this.childs, other.childs);
2419
+ }
2420
+ toDom(opts) {
2421
+ const fragment = opts.document.createDocumentFragment();
2422
+ appendChildNodes(fragment, this.childs, opts);
2423
+ return fragment;
2424
+ }
2425
+ }
2426
+
2427
+ class VNode extends VBase {
2428
+ constructor(tag, attrs, childs, key, namespace) {
2429
+ super();
2430
+ this.tag = tag;
2431
+ this.attrs = attrs ?? {};
2432
+ this.childs = childs ?? [];
2433
+ this.key = key != null ? String(key) : undefined;
2434
+ this.namespace = typeof namespace === "string" ? namespace : null;
2435
+ }
2436
+ get nodeType() {
2437
+ return 1;
2438
+ }
2439
+ isEqualTo(other) {
2440
+ if (this === other)
2441
+ return true;
2442
+ if (!(other instanceof VNode) || this.tag !== other.tag || this.key !== other.key || this.namespace !== other.namespace || this.childs.length !== other.childs.length) {
2443
+ return false;
2444
+ }
2445
+ if (this.attrs !== other.attrs) {
2446
+ for (const key in this.attrs)
2447
+ if (this.attrs[key] !== other.attrs[key])
2448
+ return false;
2449
+ for (const key in other.attrs)
2450
+ if (!Object.hasOwn(this.attrs, key))
2451
+ return false;
2452
+ }
2453
+ return childsEqual(this.childs, other.childs);
2454
+ }
2455
+ toDom(opts) {
2456
+ const doc = opts.document;
2457
+ const node = this.namespace === null ? doc.createElement(this.tag) : doc.createElementNS(this.namespace, this.tag);
2458
+ applyProperties(node, this.attrs, {});
2459
+ appendChildNodes(node, this.childs, opts);
2460
+ return node;
2461
+ }
2462
+ }
2463
+ function diffProps(a, b) {
2464
+ if (a === b)
2465
+ return null;
2466
+ let diff = null;
2467
+ for (const aKey in a) {
2468
+ if (!Object.hasOwn(b, aKey)) {
2469
+ diff ??= {};
2470
+ diff[aKey] = undefined;
2471
+ continue;
2472
+ }
2473
+ const aValue = a[aKey];
2474
+ const bValue = b[aKey];
2475
+ if (aValue === bValue)
2476
+ continue;
2477
+ if (isObject(aValue) && isObject(bValue)) {
2478
+ if (prototypesDiffer(bValue, aValue)) {
2479
+ diff ??= {};
2480
+ diff[aKey] = bValue;
2481
+ } else {
2482
+ const objectDiff = diffProps(aValue, bValue);
2483
+ if (objectDiff) {
2484
+ diff ??= {};
2485
+ diff[aKey] = objectDiff;
2486
+ }
2487
+ }
2488
+ } else {
2489
+ diff ??= {};
2490
+ diff[aKey] = bValue;
2491
+ }
2492
+ }
2493
+ for (const bKey in b) {
2494
+ if (!Object.hasOwn(a, bKey)) {
2495
+ diff ??= {};
2496
+ diff[bKey] = b[bKey];
2497
+ }
2498
+ }
2499
+ return diff;
2500
+ }
2501
+ function morphNode(domNode, source, target, opts) {
2502
+ if (source === target || source.isEqualTo(target))
2503
+ return domNode;
2504
+ const type = source.nodeType;
2505
+ if (type === target.nodeType) {
2506
+ if (type === 3 || type === 8) {
2507
+ domNode.data = target.text;
2508
+ return domNode;
2509
+ }
2510
+ if (type === 1 && source.tag === target.tag && source.namespace === target.namespace && source.key === target.key) {
2511
+ const propsDiff = diffProps(source.attrs, target.attrs);
2512
+ if (propsDiff)
2513
+ applyProperties(domNode, propsDiff, source.attrs);
2514
+ if (!target.attrs.dangerouslySetInnerHTML) {
2515
+ morphChildren(domNode, source.childs, target.childs, opts);
2516
+ }
2517
+ return domNode;
2518
+ }
2519
+ if (type === 11) {
2520
+ morphChildren(domNode, source.childs, target.childs, opts);
2521
+ return domNode;
2522
+ }
2523
+ }
2524
+ const newNode = target.toDom(opts);
2525
+ domNode.parentNode?.replaceChild(newNode, domNode);
2526
+ return newNode;
2527
+ }
2528
+ function morphChildren(parentDom, oldChilds, newChilds, opts) {
2529
+ if (oldChilds.length === 0) {
2530
+ appendChildNodes(parentDom, newChilds, opts);
2531
+ return;
2532
+ }
2533
+ if (newChilds.length === 0) {
2534
+ parentDom.replaceChildren();
2535
+ return;
2536
+ }
2537
+ if (oldChilds.length === newChilds.length) {
2538
+ let hasKey = false;
2539
+ for (let i = 0;i < oldChilds.length; i++) {
2540
+ if (getKey(oldChilds[i]) != null || getKey(newChilds[i]) != null) {
2541
+ hasKey = true;
2542
+ break;
2543
+ }
2544
+ }
2545
+ if (!hasKey) {
2546
+ let dom = parentDom.firstChild;
2547
+ for (let i = 0;i < oldChilds.length; i++) {
2548
+ const next = dom.nextSibling;
2549
+ morphNode(dom, oldChilds[i], newChilds[i], opts);
2550
+ dom = next;
2551
+ }
2552
+ return;
2553
+ }
2554
+ }
2555
+ const domNodes = Array.from(parentDom.childNodes);
2556
+ const oldKeyMap = Object.create(null);
2557
+ for (let i = 0;i < oldChilds.length; i++) {
2558
+ const key = getKey(oldChilds[i]);
2559
+ if (key != null)
2560
+ oldKeyMap[key] = i;
2561
+ }
2562
+ const used = new Uint8Array(oldChilds.length);
2563
+ let unkeyedCursor = 0;
2564
+ for (let j = 0;j < newChilds.length; j++) {
2565
+ const newChild = newChilds[j];
2566
+ const newKey = getKey(newChild);
2567
+ let oldIdx = -1;
2568
+ if (newKey != null) {
2569
+ if (newKey in oldKeyMap && !used[oldKeyMap[newKey]])
2570
+ oldIdx = oldKeyMap[newKey];
2571
+ } else {
2572
+ while (unkeyedCursor < oldChilds.length) {
2573
+ if (!used[unkeyedCursor] && getKey(oldChilds[unkeyedCursor]) == null) {
2574
+ oldIdx = unkeyedCursor++;
2575
+ break;
2576
+ }
2577
+ unkeyedCursor++;
2578
+ }
2579
+ }
2580
+ if (oldIdx >= 0) {
2581
+ used[oldIdx] = 1;
2582
+ const newDom = morphNode(domNodes[oldIdx], oldChilds[oldIdx], newChild, opts);
2583
+ const ref = parentDom.childNodes[j] ?? null;
2584
+ if (newDom !== ref)
2585
+ parentDom.insertBefore(newDom, ref);
2586
+ } else {
2587
+ const ref = parentDom.childNodes[j] ?? null;
2588
+ parentDom.insertBefore(newChild.toDom(opts), ref);
2589
+ }
2590
+ }
2591
+ for (let i = oldChilds.length - 1;i >= 0; i--)
2592
+ if (!used[i] && domNodes[i].parentNode === parentDom)
2593
+ parentDom.removeChild(domNodes[i]);
2594
+ }
2595
+ var renderCache = new WeakMap;
2596
+ function render(vnode, container, options) {
2597
+ const cached = renderCache.get(container);
2598
+ const isFragment = vnode instanceof VFragment;
2599
+ if (cached && cached.vnode instanceof VFragment === isFragment) {
2600
+ const oldDom = isFragment ? container : cached.dom;
2601
+ const newDom = morphNode(oldDom, cached.vnode, vnode, options);
2602
+ renderCache.set(container, { vnode, dom: isFragment ? container : newDom });
2603
+ return newDom;
2604
+ }
2605
+ renderCache.delete(container);
2606
+ const domNode = vnode.toDom(options);
2607
+ container.replaceChildren(domNode);
2608
+ renderCache.set(container, { vnode, dom: isFragment ? container : domNode });
2609
+ return domNode;
2610
+ }
2611
+ function h(tagName, properties, children) {
2612
+ const tag = tagName.toUpperCase();
2613
+ const props = {};
2614
+ let key, namespace;
2615
+ if (properties) {
2616
+ for (const propName in properties) {
2617
+ const propVal = properties[propName];
2618
+ switch (propName) {
2619
+ case "key":
2620
+ key = propVal;
2621
+ break;
2622
+ case "namespace":
2623
+ namespace = propVal;
2624
+ break;
2625
+ case "class":
2626
+ props.className = propVal;
2627
+ break;
2628
+ case "for":
2629
+ props.htmlFor = propVal;
2630
+ break;
2631
+ default:
2632
+ props[propName] = isHtmlAttribute(propName) ? String(propVal) : propVal;
2633
+ }
2634
+ }
2635
+ }
2636
+ const normalizedChildren = [];
2637
+ addChild(normalizedChildren, children);
2638
+ return new VNode(tag, props, normalizedChildren, key, namespace);
2639
+ }
2640
+
2641
+ // src/app.js
2642
+ var _evs = "dragstart dragover dragend touchstart touchmove touchend touchcancel".split(" ");
2643
+
2644
+ class App {
2645
+ constructor(rootNode, comps, renderer, ParseContext2) {
2646
+ this.rootNode = rootNode;
2647
+ this.comps = comps;
2648
+ this.compStack = new ComponentStack(comps);
2649
+ this.transactor = new Transactor(comps, null);
2650
+ this.ParseContext = ParseContext2;
2651
+ this.renderer = renderer;
2652
+ this.maxEventNodeDepth = Infinity;
2653
+ this._transactNextBatchId = this._evictCacheId = null;
2654
+ this._eventNames = new Set(_evs);
2655
+ this.dragInfo = this.curDragOver = null;
2656
+ this._touch = null;
2657
+ this.transactor.onTransactionPushed = (_transaction) => {
2658
+ if (this._transactNextBatchId === null)
2659
+ this._scheduleNextTransactionBatchExecution();
2660
+ };
2661
+ this._compiled = false;
2662
+ this._renderOpts = { document: rootNode.ownerDocument };
2663
+ }
2664
+ get state() {
2665
+ return this.transactor.state;
2666
+ }
2667
+ handleEvent(e) {
2668
+ const { type } = e;
2669
+ if (type[0] === "t" && type.startsWith("touch")) {
2670
+ this._handleTouchEvent(e);
2671
+ return;
2672
+ }
2673
+ this._dispatchEvent(e);
2674
+ }
2675
+ _dispatchEvent(e) {
2676
+ const { type } = e;
2677
+ const isDrag = type === "dragover" || type === "dragstart" || type === "dragend";
2678
+ const { rootNode: root, maxEventNodeDepth: maxDepth, comps } = this;
2679
+ const [path, handlers] = Path.fromEvent(e, root, maxDepth, comps, !isDrag);
2680
+ if (isDrag)
2681
+ this._handleDragEvent(e, type, path);
2682
+ if (path !== null && handlers !== null) {
2683
+ for (const handler of handlers) {
2684
+ this.transactor.transactInputNow(path, e, handler, this.dragInfo);
2685
+ }
2686
+ }
2687
+ }
2688
+ _handleTouchEvent(e) {
2689
+ const { type } = e;
2690
+ if (type === "touchstart") {
2691
+ if (this._touch !== null || e.touches.length !== 1)
2692
+ return;
2693
+ const t = e.touches[0];
2694
+ const draggable = t.target?.closest?.('[draggable="true"]');
2695
+ if (!draggable)
2696
+ return;
2697
+ this._touch = makeTouchInfo(t.identifier, t.clientX, t.clientY, draggable, false);
2698
+ return;
2699
+ }
2700
+ if (this._touch === null)
2701
+ return;
2702
+ const touch = findTouch(e, this._touch.id);
2703
+ if (touch === null)
2704
+ return;
2705
+ const { rootNode, _touch } = this;
2706
+ const { clientX, clientY } = touch;
2707
+ const fire = (type2, target) => {
2708
+ const e2 = { type: type2, target, clientX, clientY, preventDefault: NOOP };
2709
+ this._dispatchEvent(e2);
2710
+ };
2711
+ if (type === "touchmove") {
2712
+ if (!_touch.active) {
2713
+ const dx = clientX - _touch.startX;
2714
+ const dy = clientY - _touch.startY;
2715
+ if (dx * dx + dy * dy < TOUCH_DRAG_THRESHOLD_SQ)
2716
+ return;
2717
+ _touch.active = true;
2718
+ e.preventDefault();
2719
+ fire("dragstart", _touch.target);
2720
+ } else {
2721
+ e.preventDefault();
2722
+ fire("dragover", hitTest(rootNode, clientX, clientY));
2723
+ }
2724
+ return;
2725
+ }
2726
+ if (type === "touchend" || type === "touchcancel") {
2727
+ if (_touch.active) {
2728
+ if (type === "touchend")
2729
+ fire("drop", hitTest(rootNode, clientX, clientY));
2730
+ fire("dragend", _touch.target);
2731
+ }
2732
+ this._touch = null;
2733
+ }
2734
+ }
2735
+ _handleDragEvent(e, type, path) {
2736
+ if (type === "dragover") {
2737
+ const dropTarget = getClosestDropTarget(e.target, this.rootNode, 50);
2738
+ if (dropTarget !== null) {
2739
+ e.preventDefault();
2740
+ this._cleanDragOverAttrs();
2741
+ this.curDragOver = dropTarget;
2742
+ dropTarget.dataset.draggingover = this.dragInfo?.type ?? "_external";
2743
+ }
2744
+ } else if (type === "dragstart") {
2745
+ e.target.dataset.dragging = 1;
2746
+ const rootValue = this.state.val;
2747
+ const value = path.lookup(rootValue);
2748
+ const dragType = e.target.dataset.dragtype ?? "?";
2749
+ const stack = path.buildStack(this.makeStack(rootValue));
2750
+ this.dragInfo = new DragInfo(path, stack, e, value, dragType, e.target);
2751
+ } else {
2752
+ if (this.dragInfo !== null) {
2753
+ delete this.dragInfo.node.dataset.dragging;
2754
+ this.dragInfo = null;
2755
+ }
2756
+ this._cleanDragOverAttrs();
2757
+ }
2758
+ }
2759
+ makeStack(rootValue) {
2760
+ return Stack.root(this.comps, rootValue);
2761
+ }
2762
+ _cleanDragOverAttrs() {
2763
+ if (this.curDragOver !== null) {
2764
+ delete this.curDragOver.dataset.draggingover;
2765
+ this.curDragOver = null;
2387
2766
  }
2388
- for (const name of this._eventNames) {
2389
- this.rootNode.addEventListener(name, this);
2767
+ }
2768
+ render() {
2769
+ const root = this.state.val;
2770
+ const stack = this.makeStack(root);
2771
+ return render(this.renderer.renderRoot(stack, root), this.rootNode, this._renderOpts);
2772
+ }
2773
+ onChange(callback) {
2774
+ this.transactor.state.onChange(callback);
2775
+ }
2776
+ compile() {
2777
+ for (const Comp of this.comps.byId.values()) {
2778
+ Comp.compile(this.ParseContext);
2779
+ for (const key in Comp.views)
2780
+ for (const name of Comp.views[key].ctx.genEventNames())
2781
+ this._eventNames.add(name);
2390
2782
  }
2783
+ this._compiled = true;
2784
+ }
2785
+ start(opts) {
2786
+ if (!this._compiled)
2787
+ this.compile();
2788
+ for (const name of this._eventNames)
2789
+ this.rootNode.addEventListener(name, this, listenerOpts(name));
2391
2790
  this.onChange((info) => {
2392
- if (info.val !== info.old) {
2791
+ if (info.val !== info.old)
2393
2792
  this.render();
2394
- }
2395
2793
  });
2396
2794
  injectCss("tutuca-app", this.comps.compileStyles(), opts?.head ?? document.head);
2397
2795
  if (opts?.noCache) {
@@ -2404,9 +2802,8 @@ class App {
2404
2802
  }
2405
2803
  stop() {
2406
2804
  this.stopCacheEvictionInterval();
2407
- for (const name of this._eventNames) {
2408
- this.rootNode.removeEventListener(name, this);
2409
- }
2805
+ for (const name of this._eventNames)
2806
+ this.rootNode.removeEventListener(name, this, listenerOpts(name));
2410
2807
  }
2411
2808
  dispatchLogicAtRoot(name, args, opts) {
2412
2809
  return this.transactor.pushLogic(new Path([]), name, args, opts);
@@ -2420,12 +2817,10 @@ class App {
2420
2817
  this._transactNextBatchId = null;
2421
2818
  const startTs = Date.now();
2422
2819
  const t = this.transactor;
2423
- while (t.hasPendingTransactions && Date.now() - startTs < maxRunTimeMs) {
2820
+ while (t.hasPendingTransactions && Date.now() - startTs < maxRunTimeMs)
2424
2821
  t.transactNext();
2425
- }
2426
- if (t.hasPendingTransactions) {
2822
+ if (t.hasPendingTransactions)
2427
2823
  this._scheduleNextTransactionBatchExecution();
2428
- }
2429
2824
  }
2430
2825
  _scheduleNextTransactionBatchExecution() {
2431
2826
  this._transactNextBatchId = setTimeout(() => this._transactNextBatch(), 0);
@@ -2441,19 +2836,44 @@ class App {
2441
2836
  function injectCss(nodeId, style, styleTarget = document.head) {
2442
2837
  const styleNode = document.createElement("style");
2443
2838
  const currentNodeWithId = styleTarget.querySelector(`#${nodeId}`);
2444
- if (currentNodeWithId) {
2839
+ if (currentNodeWithId)
2445
2840
  styleTarget.removeChild(currentNodeWithId);
2446
- }
2447
2841
  styleNode.id = nodeId;
2448
2842
  styleNode.innerHTML = style;
2449
2843
  styleTarget.appendChild(styleNode);
2450
2844
  }
2845
+ var TOUCH_DRAG_THRESHOLD_PX = 10;
2846
+ var TOUCH_DRAG_THRESHOLD_SQ = TOUCH_DRAG_THRESHOLD_PX * TOUCH_DRAG_THRESHOLD_PX;
2847
+ var NOOP = () => {};
2848
+ function findTouch(e, id) {
2849
+ for (const t of e.changedTouches)
2850
+ if (t.identifier === id)
2851
+ return t;
2852
+ for (const t of e.touches)
2853
+ if (t.identifier === id)
2854
+ return t;
2855
+ return null;
2856
+ }
2857
+ var listenerOpts = (name) => name === "touchmove" ? { passive: false } : undefined;
2858
+ function makeTouchInfo(id, startX, startY, target, active) {
2859
+ return { id, startX, startY, target, active };
2860
+ }
2861
+ function hitTest(rootNode, x, y) {
2862
+ const root = rootNode.getRootNode();
2863
+ let el = root.elementFromPoint?.(x, y) ?? null;
2864
+ while (el?.shadowRoot) {
2865
+ const next = el.shadowRoot.elementFromPoint(x, y);
2866
+ if (next === null || next === el)
2867
+ break;
2868
+ el = next;
2869
+ }
2870
+ return el ?? rootNode;
2871
+ }
2451
2872
  function getClosestDropTarget(target, rootNode, count) {
2452
2873
  let node = target;
2453
2874
  while (count-- > 0 && node !== rootNode) {
2454
- if (node.dataset?.droptarget !== undefined) {
2875
+ if (node.dataset?.droptarget !== undefined)
2455
2876
  return node;
2456
- }
2457
2877
  node = node.parentNode;
2458
2878
  }
2459
2879
  return null;
@@ -2473,63 +2893,6 @@ class DragInfo {
2473
2893
  }
2474
2894
  }
2475
2895
 
2476
- // src/util/parsectx.js
2477
- class ParseCtxClassSetCollector extends ParseContext {
2478
- constructor(...args) {
2479
- super(...args);
2480
- this.classes = new Set;
2481
- }
2482
- _addClasses(s) {
2483
- for (const v of s.split(/\s+/)) {
2484
- this.classes.add(v);
2485
- }
2486
- }
2487
- enterMacro(macroName, macroVars, macroSlots) {
2488
- const { DOMParser: DP, Text, Comment, nodes, events, macroNodes } = this;
2489
- const frame = { macroName, macroVars, macroSlots };
2490
- const v = new ParseCtxClassSetCollector(DP, Text, Comment, nodes, events, macroNodes, frame, this);
2491
- v.classes = this.classes;
2492
- return v;
2493
- }
2494
- onAttributes(attrs, _wrapperAttrs, _textChild) {
2495
- if (Array.isArray(attrs.items)) {
2496
- for (const attr of attrs.items) {
2497
- if (attr.name !== "class") {
2498
- continue;
2499
- }
2500
- const { val, thenVal, elseVal } = attr;
2501
- if (thenVal !== undefined) {
2502
- this._maybeAddVal(thenVal);
2503
- this._maybeAddVal(elseVal);
2504
- } else {
2505
- this._maybeAddVal(val);
2506
- }
2507
- }
2508
- } else {
2509
- const attr = attrs.items.class;
2510
- if (attr) {
2511
- this._addClasses(attr);
2512
- }
2513
- }
2514
- }
2515
- _maybeAddVal(value) {
2516
- if (!this._maybeAddStrTpl(value) && typeof value?.val === "string") {
2517
- this._addClasses(value.val);
2518
- }
2519
- }
2520
- _maybeAddStrTpl(value) {
2521
- if (value?.vals !== undefined) {
2522
- for (const val of value.vals) {
2523
- if (val instanceof ConstVal && val.val !== "") {
2524
- this._addClasses(val.val);
2525
- }
2526
- }
2527
- return true;
2528
- }
2529
- return false;
2530
- }
2531
- }
2532
-
2533
2896
  // deps/immutable.js
2534
2897
  function invariant(condition, error) {
2535
2898
  if (!condition)
@@ -3191,28 +3554,28 @@ function hashCollection(collection) {
3191
3554
  }
3192
3555
  const ordered = isOrdered(collection);
3193
3556
  const keyed = isKeyed(collection);
3194
- let h = ordered ? 1 : 0;
3557
+ let h2 = ordered ? 1 : 0;
3195
3558
  collection.__iterate(keyed ? ordered ? (v, k) => {
3196
- h = 31 * h + hashMerge(hash(v), hash(k)) | 0;
3559
+ h2 = 31 * h2 + hashMerge(hash(v), hash(k)) | 0;
3197
3560
  } : (v, k) => {
3198
- h = h + hashMerge(hash(v), hash(k)) | 0;
3561
+ h2 = h2 + hashMerge(hash(v), hash(k)) | 0;
3199
3562
  } : ordered ? (v) => {
3200
- h = 31 * h + hash(v) | 0;
3563
+ h2 = 31 * h2 + hash(v) | 0;
3201
3564
  } : (v) => {
3202
- h = h + hash(v) | 0;
3565
+ h2 = h2 + hash(v) | 0;
3203
3566
  });
3204
- return murmurHashOfSize(collection.size, h);
3567
+ return murmurHashOfSize(collection.size, h2);
3205
3568
  }
3206
3569
  var hashMerge = (a, b) => a ^ b + 2654435769 + (a << 6) + (a >> 2) | 0;
3207
- function murmurHashOfSize(size, h) {
3208
- h = Math.imul(h, 3432918353);
3209
- h = Math.imul(h << 15 | h >>> -15, 461845907);
3210
- h = Math.imul(h << 13 | h >>> -13, 5);
3211
- h = (h + 3864292196 | 0) ^ size;
3212
- h = Math.imul(h ^ h >>> 16, 2246822507);
3213
- h = Math.imul(h ^ h >>> 13, 3266489909);
3214
- h = smi(h ^ h >>> 16);
3215
- return h;
3570
+ function murmurHashOfSize(size, h2) {
3571
+ h2 = Math.imul(h2, 3432918353);
3572
+ h2 = Math.imul(h2 << 15 | h2 >>> -15, 461845907);
3573
+ h2 = Math.imul(h2 << 13 | h2 >>> -13, 5);
3574
+ h2 = (h2 + 3864292196 | 0) ^ size;
3575
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507);
3576
+ h2 = Math.imul(h2 ^ h2 >>> 13, 3266489909);
3577
+ h2 = smi(h2 ^ h2 >>> 16);
3578
+ return h2;
3216
3579
  }
3217
3580
  function quoteString(value) {
3218
3581
  try {
@@ -5325,7 +5688,7 @@ var List = (value) => {
5325
5688
  }
5326
5689
  assertNotInfinite(size);
5327
5690
  if (size > 0 && size < SIZE) {
5328
- return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));
5691
+ return makeList(0, size, SHIFT, null, new VNode2(iter.toArray()));
5329
5692
  }
5330
5693
  return empty.withMutations((list) => {
5331
5694
  list.setSize(size);
@@ -5516,7 +5879,7 @@ class ListImpl extends IndexedCollectionImpl {
5516
5879
  }
5517
5880
  List.isList = isList;
5518
5881
 
5519
- class VNode {
5882
+ class VNode2 {
5520
5883
  constructor(array, ownerID) {
5521
5884
  this.array = array;
5522
5885
  this.ownerID = ownerID;
@@ -5527,7 +5890,7 @@ class VNode {
5527
5890
  }
5528
5891
  const originIndex = index >>> level & MASK;
5529
5892
  if (originIndex >= this.array.length) {
5530
- return new VNode([], ownerID);
5893
+ return new VNode2([], ownerID);
5531
5894
  }
5532
5895
  const removingFirst = originIndex === 0;
5533
5896
  let newChild;
@@ -5753,7 +6116,7 @@ function editableVNode(node, ownerID) {
5753
6116
  if (ownerID && ownerID === node?.ownerID) {
5754
6117
  return node;
5755
6118
  }
5756
- return new VNode(node?.array.slice() ?? [], ownerID);
6119
+ return new VNode2(node?.array.slice() ?? [], ownerID);
5757
6120
  }
5758
6121
  function listNodeFor(list, rawIndex) {
5759
6122
  if (rawIndex >= getTailOffset(list._capacity)) {
@@ -5791,7 +6154,7 @@ function setListBounds(list, begin, end) {
5791
6154
  let newRoot = list._root;
5792
6155
  let offsetShift = 0;
5793
6156
  while (newOrigin + offsetShift < 0) {
5794
- newRoot = new VNode(newRoot?.array.length ? [undefined, newRoot] : [], owner);
6157
+ newRoot = new VNode2(newRoot?.array.length ? [undefined, newRoot] : [], owner);
5795
6158
  newLevel += SHIFT;
5796
6159
  offsetShift += 1 << newLevel;
5797
6160
  }
@@ -5804,11 +6167,11 @@ function setListBounds(list, begin, end) {
5804
6167
  const oldTailOffset = getTailOffset(oldCapacity);
5805
6168
  const newTailOffset = getTailOffset(newCapacity);
5806
6169
  while (newTailOffset >= 1 << newLevel + SHIFT) {
5807
- newRoot = new VNode(newRoot?.array.length ? [newRoot] : [], owner);
6170
+ newRoot = new VNode2(newRoot?.array.length ? [newRoot] : [], owner);
5808
6171
  newLevel += SHIFT;
5809
6172
  }
5810
6173
  const oldTail = list._tail;
5811
- let newTail = newTailOffset < oldTailOffset ? listNodeFor(list, newCapacity - 1) : newTailOffset > oldTailOffset ? new VNode([], owner) : oldTail;
6174
+ let newTail = newTailOffset < oldTailOffset ? listNodeFor(list, newCapacity - 1) : newTailOffset > oldTailOffset ? new VNode2([], owner) : oldTail;
5812
6175
  if (oldTail && newTailOffset > oldTailOffset && newOrigin < oldCapacity && oldTail.array.length) {
5813
6176
  newRoot = editableVNode(newRoot, owner);
5814
6177
  let node = newRoot;
@@ -6924,14 +7287,11 @@ class Field {
6924
7287
  return { type, defaultValue: dv?.toJS ? dv.toJS() : dv };
6925
7288
  }
6926
7289
  getFirstFailingCheck(v) {
6927
- if (!this.typeCheck.isValid(v)) {
7290
+ if (!this.typeCheck.isValid(v))
6928
7291
  return this.typeCheck;
6929
- }
6930
- for (const check of this.checks) {
6931
- if (!check.isValid(v)) {
7292
+ for (const check of this.checks)
7293
+ if (!check.isValid(v))
6932
7294
  return check;
6933
- }
6934
- }
6935
7295
  return null;
6936
7296
  }
6937
7297
  isValid(v) {
@@ -6942,9 +7302,8 @@ class Field {
6942
7302
  return this;
6943
7303
  }
6944
7304
  coerceOr(v, defaultValue = null) {
6945
- if (this.isValid(v)) {
7305
+ if (this.isValid(v))
6946
7306
  return v;
6947
- }
6948
7307
  const v1 = this.coercer(v);
6949
7308
  return this.isValid(v1) ? v1 : defaultValue;
6950
7309
  }
@@ -7102,9 +7461,8 @@ function extendProtoForKeyed(proto, name, uname) {
7102
7461
  proto[`updateIn${uname}At`] = function(i, fn) {
7103
7462
  const col = this.get(name);
7104
7463
  const v = col.get(i, NONE2);
7105
- if (v !== NONE2) {
7464
+ if (v !== NONE2)
7106
7465
  return this.set(name, col.set(i, fn(v)));
7107
- }
7108
7466
  console.warn("key", i, "not found in", name, col);
7109
7467
  return this;
7110
7468
  };
@@ -7204,19 +7562,17 @@ class ClassBuilder {
7204
7562
  const args = {};
7205
7563
  for (const key in inArgs) {
7206
7564
  const field = fields[key];
7207
- if (compFields.has(key)) {
7565
+ if (compFields.has(key))
7208
7566
  args[key] = mkCompField(field, opts.scope, inArgs[key]);
7209
- } else if (field === undefined) {
7567
+ else if (field === undefined) {
7210
7568
  console.warn("extra argument to constructor:", name, key, inArgs);
7211
7569
  continue;
7212
7570
  }
7213
7571
  args[key] = field.coerceOrDefault(inArgs[key]);
7214
7572
  }
7215
- for (const key of compFields) {
7216
- if (args[key] === undefined) {
7573
+ for (const key of compFields)
7574
+ if (args[key] === undefined)
7217
7575
  args[key] = mkCompField(fields[key], opts.scope, inArgs[key]);
7218
- }
7219
- }
7220
7576
  return this(args);
7221
7577
  }
7222
7578
  };
@@ -7243,9 +7599,8 @@ class ClassBuilder {
7243
7599
  return this._mergeProto(this._statics, proto, "static");
7244
7600
  }
7245
7601
  _mergeProto(target, proto, _name) {
7246
- for (const k in proto) {
7602
+ for (const k in proto)
7247
7603
  target[k] = proto[k];
7248
- }
7249
7604
  return this;
7250
7605
  }
7251
7606
  addField(name, dval, FieldCls) {
@@ -7277,70 +7632,74 @@ function classFromData(name, { fields = {}, methods, statics }) {
7277
7632
  for (const field in fields) {
7278
7633
  const value = fields[field];
7279
7634
  const type = typeof value;
7280
- if (type === "string") {
7635
+ if (type === "string")
7281
7636
  b.addField(field, value, FieldString);
7282
- } else if (type === "number") {
7637
+ else if (type === "number")
7283
7638
  b.addField(field, value, FieldFloat);
7284
- } else if (type === "boolean") {
7639
+ else if (type === "boolean")
7285
7640
  b.addField(field, value, FieldBool);
7286
- } else if (List.isList(value) || Array.isArray(value)) {
7641
+ else if (List.isList(value) || Array.isArray(value))
7287
7642
  b.addField(field, List(value), FieldList);
7288
- } else if (Set2.isSet(value) || value instanceof Set) {
7643
+ else if (Set2.isSet(value) || value instanceof Set)
7289
7644
  b.addField(field, Set2(value), FieldSet);
7290
- } else if (OrderedMap.isOrderedMap(value)) {
7645
+ else if (OrderedMap.isOrderedMap(value))
7291
7646
  b.addField(field, value, FieldOMap);
7292
- } else if (value?.type && value?.defaultValue !== undefined) {
7647
+ else if (value?.type && value?.defaultValue !== undefined) {
7293
7648
  const Field2 = fieldsByTypeName[value.type] ?? FieldAny;
7294
7649
  b.addField(field, new Field2().coerceOr(value.defaultValue), Field2);
7295
- } else if (value?.component && value?.args !== undefined) {
7650
+ } else if (value?.component && value?.args !== undefined)
7296
7651
  b.addCompField(field, value.component, value.args);
7297
- } else if (Map2.isMap(value) || value?.constructor === Object) {
7652
+ else if (Map2.isMap(value) || value?.constructor === Object)
7298
7653
  b.addField(field, Map2(value), FieldMap);
7299
- } else {
7654
+ else {
7300
7655
  const Field2 = fieldsByClass.get(value?.constructor) ?? FieldAny;
7301
7656
  b.addField(field, value, Field2);
7302
7657
  }
7303
7658
  }
7304
- if (methods) {
7659
+ if (methods)
7305
7660
  b.methods(methods);
7306
- }
7307
- if (statics) {
7661
+ if (statics)
7308
7662
  b.statics(statics);
7309
- }
7310
7663
  return b.build();
7311
7664
  }
7312
- var component = (opts) => new Component(opts.name ?? "Comp", classFromData(opts.name, opts), opts.view ?? "Not Defined", opts.views, opts.style, opts.commonStyle ?? "", opts.globalStyle ?? "", opts.computed, opts.input, opts.logic, opts.bubble, opts.response, opts.alter, opts.dynamic, opts.on);
7665
+ var component = (opts) => new Component(classFromData(opts.name, opts), opts);
7313
7666
 
7314
7667
  // src/renderer.js
7315
7668
  var DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
7316
7669
 
7317
7670
  class Renderer {
7318
- constructor(comps, h, fragment, comment, renderFn, getSeqInfo, cache) {
7671
+ constructor(comps) {
7319
7672
  this.comps = comps;
7320
- this.h = h;
7321
- this.fragment = fragment;
7322
- this.renderComment = comment;
7323
- this.renderFn = renderFn;
7324
- this.getSeqInfo = getSeqInfo ?? basicGetSeqInfo;
7325
- this.cache = cache ?? new WeakMapDomCache;
7673
+ this.cache = new WeakMapDomCache;
7674
+ }
7675
+ getSeqInfo(seq) {
7676
+ return isIndexed(seq) ? imIndexedIter : isKeyed(seq) ? imKeyedIter : seqInfoByClass.get(seq?.constructor) ?? unkIter;
7677
+ }
7678
+ renderTag(tag, attrs, childs) {
7679
+ return h(tag, attrs, childs);
7680
+ }
7681
+ renderFragment(childs) {
7682
+ return new VFragment(childs);
7683
+ }
7684
+ renderComment(text) {
7685
+ return new VComment(text);
7326
7686
  }
7327
7687
  setNullCache() {
7328
7688
  this.cache = new NullDomCache;
7329
7689
  }
7330
7690
  renderToDOM(stack, val) {
7331
7691
  const rootNode = document.createElement("div");
7332
- this.renderFn(this.h("div", null, [this.renderRoot(stack, val)]), rootNode);
7692
+ const rOpts = { document };
7693
+ render(h("div", null, [this.renderRoot(stack, val)]), rootNode, rOpts);
7333
7694
  return rootNode.childNodes[0];
7334
7695
  }
7335
7696
  renderToString(stack, val, cleanAttrs = true) {
7336
- const dom = this.renderToDOM(stack, val, this.renderFn);
7697
+ const dom = this.renderToDOM(stack, val);
7337
7698
  if (cleanAttrs) {
7338
7699
  const nodes = dom.querySelectorAll("[data-nid],[data-cid],[data-eid]");
7339
- for (const { dataset } of nodes) {
7340
- for (const name of DATASET_ATTRS) {
7700
+ for (const { dataset } of nodes)
7701
+ for (const name of DATASET_ATTRS)
7341
7702
  delete dataset[name];
7342
- }
7343
- }
7344
7703
  }
7345
7704
  return dom.innerHTML;
7346
7705
  }
@@ -7356,560 +7715,194 @@ class Renderer {
7356
7715
  _rValComp(stack, val, comp, nid, key, viewName) {
7357
7716
  const cacheKey = `${viewName ?? stack.viewsId ?? ""}${nid}-${key}`;
7358
7717
  const cachedNode = this.cache.get(val, cacheKey);
7359
- if (cachedNode) {
7718
+ if (cachedNode)
7360
7719
  return cachedNode;
7361
- }
7362
7720
  const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
7363
- const meta = this.renderMetadata("Comp", { nid });
7364
- const dom = this.renderFragment([meta, this.renderView(view, stack)]);
7721
+ const meta = this._renderMetadata({ $: "Comp", nid });
7722
+ const dom = new VFragment([meta, this.renderView(view, stack)]);
7365
7723
  this.cache.set(val, cacheKey, dom);
7366
7724
  return dom;
7367
7725
  }
7368
7726
  pushEachEntry(r, nid, attrName, key, dom) {
7369
- r.push(this.renderMetadata("Each", { nid, [attrName]: key }), dom);
7727
+ r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
7370
7728
  }
7371
7729
  renderEach(stack, iterInfo, nodeId, viewName) {
7372
7730
  const { seq, filter, loopWith } = iterInfo.eval(stack);
7373
- const [attrName, gen] = this.getSeqInfo(seq);
7374
7731
  const r = [];
7375
7732
  const iterData = loopWith.call(stack.it, seq);
7376
- for (const [key, value] of gen(seq)) {
7733
+ this.getSeqInfo(seq)(seq, (key, value, attrName) => {
7377
7734
  if (filter.call(stack.it, key, value, iterData)) {
7378
7735
  const newStack = stack.enter(value, { key }, true);
7379
7736
  const dom = this.renderIt(newStack, nodeId, key, viewName);
7380
7737
  this.pushEachEntry(r, nodeId, attrName, key, dom);
7381
7738
  }
7382
- }
7739
+ });
7383
7740
  return r;
7384
7741
  }
7385
7742
  renderEachWhen(stack, iterInfo, view, nid) {
7386
7743
  const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
7387
- const [attrName, gen] = this.getSeqInfo(seq);
7388
7744
  const r = [];
7389
7745
  const iterData = loopWith.call(stack.it, seq);
7390
- for (const [key, value] of gen(seq)) {
7391
- if (filter.call(stack.it, key, value, iterData)) {
7746
+ const it = stack.it;
7747
+ this.getSeqInfo(seq)(seq, (key, value, attrName) => {
7748
+ if (filter.call(it, key, value, iterData)) {
7392
7749
  const bindings = { key, value };
7393
7750
  const cacheKey = `${nid}-${key}`;
7394
7751
  let cachedNode;
7395
7752
  if (enricher) {
7396
- enricher.call(stack.it, bindings, key, value, iterData);
7397
- cachedNode = this.cache.get2(stack.it, value, cacheKey);
7398
- } else {
7753
+ enricher.call(it, bindings, key, value, iterData);
7754
+ cachedNode = this.cache.get2(it, value, cacheKey);
7755
+ } else
7399
7756
  cachedNode = this.cache.get(value, cacheKey);
7400
- }
7401
7757
  if (cachedNode) {
7402
7758
  this.pushEachEntry(r, nid, attrName, key, cachedNode);
7403
- continue;
7759
+ return;
7404
7760
  }
7405
7761
  const newStack = stack.enter(value, bindings, false);
7406
7762
  const dom = this.renderView(view, newStack);
7407
7763
  this.pushEachEntry(r, nid, attrName, key, dom);
7408
- if (enricher) {
7409
- this.cache.set2(stack.it, value, cacheKey, dom);
7410
- } else {
7764
+ if (enricher)
7765
+ this.cache.set2(it, value, cacheKey, dom);
7766
+ else
7411
7767
  this.cache.set(value, cacheKey, dom);
7412
- }
7413
7768
  }
7414
- }
7769
+ });
7415
7770
  return r;
7416
7771
  }
7417
7772
  renderView(view, stack) {
7418
- if (stack.binds.tail !== null) {
7419
- for (const binds of stack.binds.tail) {
7420
- if (!binds.isFrame)
7421
- continue;
7422
- if (stack.it !== binds.it)
7773
+ let n = stack.binds[1];
7774
+ while (n !== null) {
7775
+ const b = n[0];
7776
+ if (b.isFrame) {
7777
+ if (stack.it !== b.it)
7423
7778
  break;
7424
- console.error("recursion detected", stack.it, binds.it);
7425
- return this.renderComment("RECURSION AVOIDED");
7426
- }
7427
- }
7428
- return view.render(stack, this);
7429
- }
7430
- renderText(text) {
7431
- return text;
7432
- }
7433
- renderMetadata(type, info) {
7434
- info.$ = type;
7435
- return this.renderComment(`§${JSON.stringify(info)}§`);
7436
- }
7437
- renderEmpty() {
7438
- return null;
7439
- }
7440
- renderTag(tagName, attrs, childs) {
7441
- return this.h(tagName, attrs, childs);
7442
- }
7443
- renderFragment(childs) {
7444
- return this.fragment(childs);
7445
- }
7446
- }
7447
- function* imIndexedEntries(seq) {
7448
- let i = 0;
7449
- for (const v of seq)
7450
- yield [i++, v];
7451
- }
7452
- function* imKeyedEntries(obj) {
7453
- for (const [key, value] of obj.toSeq().entries())
7454
- yield [key, value];
7455
- }
7456
- var seqInfoByClass = new Map;
7457
- var idxInfo = ["si", imIndexedEntries];
7458
- var keyInfo = ["sk", imKeyedEntries];
7459
- var unkInfo = ["si", function* nullEntries(_obj) {}];
7460
- function basicGetSeqInfo(seq) {
7461
- return isIndexed(seq) ? idxInfo : isKeyed(seq) ? keyInfo : seqInfoByClass.get(seq?.constructor) ?? unkInfo;
7462
- }
7463
-
7464
- // extra/klist.js
7465
- class KList {
7466
- constructor(items = Map2(), order = List()) {
7467
- this.items = items;
7468
- this.order = order;
7469
- this.$ = 0;
7470
- }
7471
- _clonish(items, order) {
7472
- return new KList(items, order, this.$);
7473
- }
7474
- toJS() {
7475
- return this.order.toArray().map((k) => this.items.get(k));
7476
- }
7477
- set(k, v) {
7478
- const newOrder = this.items.has(k) ? this.order : this.order.push(k);
7479
- return this._clonish(this.items.set(k, v), newOrder, this.$);
7480
- }
7481
- get(k, dval = null) {
7482
- return this.items.get(k, dval);
7483
- }
7484
- _nextFreeKey() {
7485
- let cur = this.$;
7486
- while (true) {
7487
- const key = `§${cur}§`;
7488
- if (!this.items.has(key)) {
7489
- return [key, cur];
7490
- }
7491
- cur += 1;
7492
- }
7493
- }
7494
- push(v) {
7495
- const [key, next$] = this._nextFreeKey();
7496
- const newKList = this.set(key, v);
7497
- newKList.$ = next$;
7498
- return newKList;
7499
- }
7500
- get size() {
7501
- return this.items.size;
7502
- }
7503
- delete(k) {
7504
- if (this.items.has(k)) {
7505
- const newOrder = this.order.delete(this.order.indexOf(k));
7506
- return this._clonish(this.items.delete(k), newOrder);
7507
- }
7508
- return this;
7509
- }
7510
- moveKeyBeforeKey(k1, k2) {
7511
- const { order } = this;
7512
- return this.moveKeyIndexToIndex(order.indexOf(k1), order.indexOf(k2), 0);
7513
- }
7514
- moveKeyAfterKey(k1, k2) {
7515
- const { order } = this;
7516
- return this.moveKeyIndexToIndex(order.indexOf(k1), order.indexOf(k2), 1);
7517
- }
7518
- moveKeyIndexToIndex(source, target, offset) {
7519
- if (source === -1 || target === -1 || source === target) {
7520
- return this;
7521
- }
7522
- const { order } = this;
7523
- const newPos = target + offset;
7524
- const oldPos = newPos < source ? source + 1 : source;
7525
- const newOrder = order.insert(newPos, order.get(source)).delete(oldPos);
7526
- return this._clonish(this.items, newOrder);
7527
- }
7528
- }
7529
- var klistCoercer = (_) => null;
7530
-
7531
- class CheckTypeKList {
7532
- isValid(v) {
7533
- return v instanceof KList;
7534
- }
7535
- getMessage(_v) {
7536
- return "KList expected";
7537
- }
7538
- }
7539
- var CHECK_TYPE_KLIST = new CheckTypeKList;
7540
-
7541
- class FieldKList extends Field {
7542
- constructor(name, defaultValue = new KList) {
7543
- super("KList", name, CHECK_TYPE_KLIST, klistCoercer, defaultValue);
7544
- }
7545
- extendProtoForType(proto, uname) {
7546
- extendProtoForKeyed(proto, this.name, uname);
7547
- const { name } = this;
7548
- extendProtoForKeyed(proto, name, uname);
7549
- proto[`pushIn${uname}`] = function(v) {
7550
- return this.set(name, this.get(name).push(v));
7551
- };
7552
- }
7553
- }
7554
- fieldsByClass.set(KList, FieldKList);
7555
- function* klistEntries(seq) {
7556
- for (const k of seq.order) {
7557
- yield [k, seq.items.get(k)];
7558
- }
7559
- }
7560
- seqInfoByClass.set(KList, ["data-sk", klistEntries]);
7561
- // src/vdom.js
7562
- var isHtmlAttribute = (propName) => propName[4] === "-" && (propName[0] === "d" || propName[0] === "a");
7563
- var isObject = (v) => v !== null && typeof v === "object";
7564
- var prototypesDiffer = (a, b) => Object.getPrototypeOf(a) !== Object.getPrototypeOf(b);
7565
- function applyProperties(node, props, previous) {
7566
- for (const propName in props) {
7567
- const propValue = props[propName];
7568
- if (propValue === undefined) {
7569
- removeProperty(node, propName, previous);
7570
- } else if (isHtmlAttribute(propName)) {
7571
- node.setAttribute(propName, propValue);
7572
- } else if (propName === "dangerouslySetInnerHTML") {
7573
- node.innerHTML = propValue.__html ?? "";
7574
- } else if (isObject(propValue)) {
7575
- patchObject(node, previous, propName, propValue);
7576
- } else if (propName === "className") {
7577
- node.setAttribute("class", propValue);
7578
- } else {
7579
- node[propName] = propValue;
7580
- }
7581
- }
7582
- }
7583
- function removeProperty(node, propName, previous) {
7584
- const previousValue = previous[propName];
7585
- if (propName === "dangerouslySetInnerHTML") {
7586
- node.replaceChildren();
7587
- } else if (propName === "className") {
7588
- node.removeAttribute("class");
7589
- } else if (propName === "htmlFor") {
7590
- node.removeAttribute("for");
7591
- } else if (typeof previousValue === "string" || isHtmlAttribute(propName)) {
7592
- node.removeAttribute(propName);
7593
- } else {
7594
- node[propName] = null;
7595
- }
7596
- }
7597
- function patchObject(node, previous, propName, propValue) {
7598
- const previousValue = previous?.[propName];
7599
- if (isObject(previousValue) && prototypesDiffer(previousValue, propValue)) {
7600
- node[propName] = propValue;
7601
- return;
7602
- }
7603
- if (!isObject(node[propName])) {
7604
- node[propName] = {};
7605
- }
7606
- const target = node[propName];
7607
- for (const k in propValue) {
7608
- target[k] = propValue[k];
7609
- }
7610
- }
7611
-
7612
- class VBase {
7613
- }
7614
- var getKey = (child) => child instanceof VNode2 ? child.key : undefined;
7615
- var isIterable = (obj) => obj != null && typeof obj !== "string" && typeof obj[Symbol.iterator] === "function";
7616
- function childsEqual(a, b) {
7617
- for (let i = 0;i < a.length; i++) {
7618
- if (!a[i].isEqualTo(b[i]))
7619
- return false;
7620
- }
7621
- return true;
7622
- }
7623
- function appendChildNodes(parent, childs, opts) {
7624
- for (const child of childs) {
7625
- parent.appendChild(child.toDom(opts));
7626
- }
7627
- }
7628
- function addChild(normalizedChildren, child) {
7629
- if (child == null)
7630
- return;
7631
- if (isIterable(child)) {
7632
- for (const c of child) {
7633
- addChild(normalizedChildren, c);
7634
- }
7635
- } else if (child instanceof VBase) {
7636
- if (child instanceof VFragment) {
7637
- normalizedChildren.push(...child.childs);
7638
- } else {
7639
- normalizedChildren.push(child);
7640
- }
7641
- } else {
7642
- normalizedChildren.push(new VText(child));
7643
- }
7644
- }
7645
-
7646
- class VText extends VBase {
7647
- constructor(text) {
7648
- super();
7649
- this.text = String(text);
7650
- }
7651
- get nodeType() {
7652
- return 3;
7653
- }
7654
- isEqualTo(other) {
7655
- return other instanceof VText && this.text === other.text;
7656
- }
7657
- toDom(opts) {
7658
- return opts.document.createTextNode(this.text);
7659
- }
7660
- }
7661
-
7662
- class VComment extends VBase {
7663
- constructor(text) {
7664
- super();
7665
- this.text = text;
7666
- }
7667
- get nodeType() {
7668
- return 8;
7669
- }
7670
- isEqualTo(other) {
7671
- return other instanceof VComment && this.text === other.text;
7672
- }
7673
- toDom(opts) {
7674
- return opts.document.createComment(this.text);
7675
- }
7676
- }
7677
-
7678
- class VFragment extends VBase {
7679
- constructor(childs) {
7680
- super();
7681
- this.childs = [];
7682
- addChild(this.childs, childs);
7683
- }
7684
- get nodeType() {
7685
- return 11;
7686
- }
7687
- isEqualTo(other) {
7688
- if (!(other instanceof VFragment) || this.childs.length !== other.childs.length) {
7689
- return false;
7779
+ console.error("recursion detected", stack.it, b.it);
7780
+ return new VComment("RECURSION AVOIDED");
7781
+ }
7782
+ n = n[1];
7690
7783
  }
7691
- return childsEqual(this.childs, other.childs);
7784
+ return view.render(stack, this);
7692
7785
  }
7693
- toDom(opts) {
7694
- const fragment = opts.document.createDocumentFragment();
7695
- appendChildNodes(fragment, this.childs, opts);
7696
- return fragment;
7786
+ _renderMetadata(info) {
7787
+ return new VComment(`§${JSON.stringify(info)}§`);
7697
7788
  }
7698
7789
  }
7790
+ var imIndexedIter = (seq, visit) => {
7791
+ let i = 0;
7792
+ for (const v of seq)
7793
+ visit(i++, v, "si");
7794
+ };
7795
+ var imKeyedIter = (seq, visit) => {
7796
+ for (const [k, v] of seq.toSeq().entries())
7797
+ visit(k, v, "sk");
7798
+ };
7799
+ var unkIter = () => {};
7800
+ var seqInfoByClass = new Map;
7699
7801
 
7700
- class VNode2 extends VBase {
7701
- constructor(tag, attrs, childs, key, namespace) {
7702
- super();
7703
- this.tag = tag;
7704
- this.attrs = attrs ?? {};
7705
- this.childs = childs ?? [];
7706
- this.key = key != null ? String(key) : undefined;
7707
- this.namespace = typeof namespace === "string" ? namespace : null;
7708
- }
7709
- get nodeType() {
7710
- return 1;
7802
+ // extra/klist.js
7803
+ class KList {
7804
+ constructor(items = Map2(), order = List()) {
7805
+ this.items = items;
7806
+ this.order = order;
7807
+ this.$ = 0;
7711
7808
  }
7712
- isEqualTo(other) {
7713
- if (!(other instanceof VNode2) || this.tag !== other.tag || this.key !== other.key || this.namespace !== other.namespace || this.childs.length !== other.childs.length) {
7714
- return false;
7715
- }
7716
- for (const key in this.attrs) {
7717
- if (this.attrs[key] !== other.attrs[key]) {
7718
- return false;
7719
- }
7720
- }
7721
- for (const key in other.attrs) {
7722
- if (!Object.hasOwn(this.attrs, key)) {
7723
- return false;
7724
- }
7725
- }
7726
- return childsEqual(this.childs, other.childs);
7809
+ _clonish(items, order) {
7810
+ return new KList(items, order, this.$);
7727
7811
  }
7728
- toDom(opts) {
7729
- const doc = opts.document;
7730
- const node = this.namespace === null ? doc.createElement(this.tag) : doc.createElementNS(this.namespace, this.tag);
7731
- applyProperties(node, this.attrs, {});
7732
- appendChildNodes(node, this.childs, opts);
7733
- return node;
7812
+ toJS() {
7813
+ return this.order.toArray().map((k) => this.items.get(k));
7734
7814
  }
7735
- }
7736
- function diffProps(a, b) {
7737
- let diff = null;
7738
- for (const aKey in a) {
7739
- if (!Object.hasOwn(b, aKey)) {
7740
- diff ??= {};
7741
- diff[aKey] = undefined;
7742
- continue;
7743
- }
7744
- const aValue = a[aKey];
7745
- const bValue = b[aKey];
7746
- if (aValue === bValue)
7747
- continue;
7748
- if (isObject(aValue) && isObject(bValue)) {
7749
- if (prototypesDiffer(bValue, aValue)) {
7750
- diff ??= {};
7751
- diff[aKey] = bValue;
7752
- } else {
7753
- const objectDiff = diffProps(aValue, bValue);
7754
- if (objectDiff) {
7755
- diff ??= {};
7756
- diff[aKey] = objectDiff;
7757
- }
7758
- }
7759
- } else {
7760
- diff ??= {};
7761
- diff[aKey] = bValue;
7762
- }
7815
+ set(k, v) {
7816
+ const newOrder = this.items.has(k) ? this.order : this.order.push(k);
7817
+ return this._clonish(this.items.set(k, v), newOrder, this.$);
7763
7818
  }
7764
- for (const bKey in b) {
7765
- if (!Object.hasOwn(a, bKey)) {
7766
- diff ??= {};
7767
- diff[bKey] = b[bKey];
7768
- }
7819
+ get(k, dval = null) {
7820
+ return this.items.get(k, dval);
7769
7821
  }
7770
- return diff;
7771
- }
7772
- function morphNode(domNode, source, target, opts) {
7773
- if (source === target || source.isEqualTo(target))
7774
- return domNode;
7775
- const type = source.nodeType;
7776
- if (type === target.nodeType) {
7777
- if (type === 3 || type === 8) {
7778
- domNode.data = target.text;
7779
- return domNode;
7780
- }
7781
- if (type === 1 && source.tag === target.tag && source.namespace === target.namespace && source.key === target.key) {
7782
- const propsDiff = diffProps(source.attrs, target.attrs);
7783
- if (propsDiff)
7784
- applyProperties(domNode, propsDiff, source.attrs);
7785
- if (!target.attrs.dangerouslySetInnerHTML) {
7786
- morphChildren(domNode, source.childs, target.childs, opts);
7822
+ _nextFreeKey() {
7823
+ let cur = this.$;
7824
+ while (true) {
7825
+ const key = `§${cur}§`;
7826
+ if (!this.items.has(key)) {
7827
+ return [key, cur];
7787
7828
  }
7788
- return domNode;
7789
- }
7790
- if (type === 11) {
7791
- morphChildren(domNode, source.childs, target.childs, opts);
7792
- return domNode;
7829
+ cur += 1;
7793
7830
  }
7794
7831
  }
7795
- const newNode = target.toDom(opts);
7796
- domNode.parentNode?.replaceChild(newNode, domNode);
7797
- return newNode;
7798
- }
7799
- function morphChildren(parentDom, oldChilds, newChilds, opts) {
7800
- if (oldChilds.length === 0) {
7801
- appendChildNodes(parentDom, newChilds, opts);
7802
- return;
7803
- }
7804
- if (newChilds.length === 0) {
7805
- parentDom.replaceChildren();
7806
- return;
7832
+ push(v) {
7833
+ const [key, next$] = this._nextFreeKey();
7834
+ const newKList = this.set(key, v);
7835
+ newKList.$ = next$;
7836
+ return newKList;
7807
7837
  }
7808
- const domNodes = Array.from(parentDom.childNodes);
7809
- const oldKeyMap = Object.create(null);
7810
- for (let i = 0;i < oldChilds.length; i++) {
7811
- const key = getKey(oldChilds[i]);
7812
- if (key != null)
7813
- oldKeyMap[key] = i;
7838
+ get size() {
7839
+ return this.items.size;
7814
7840
  }
7815
- const used = new Uint8Array(oldChilds.length);
7816
- let unkeyedCursor = 0;
7817
- for (let j = 0;j < newChilds.length; j++) {
7818
- const newChild = newChilds[j];
7819
- const newKey = getKey(newChild);
7820
- let oldIdx = -1;
7821
- if (newKey != null) {
7822
- if (newKey in oldKeyMap && !used[oldKeyMap[newKey]]) {
7823
- oldIdx = oldKeyMap[newKey];
7824
- }
7825
- } else {
7826
- while (unkeyedCursor < oldChilds.length) {
7827
- if (!used[unkeyedCursor] && getKey(oldChilds[unkeyedCursor]) == null) {
7828
- oldIdx = unkeyedCursor++;
7829
- break;
7830
- }
7831
- unkeyedCursor++;
7832
- }
7833
- }
7834
- if (oldIdx >= 0) {
7835
- used[oldIdx] = 1;
7836
- const newDom = morphNode(domNodes[oldIdx], oldChilds[oldIdx], newChild, opts);
7837
- const ref = parentDom.childNodes[j] ?? null;
7838
- if (newDom !== ref)
7839
- parentDom.insertBefore(newDom, ref);
7840
- } else {
7841
- const ref = parentDom.childNodes[j] ?? null;
7842
- parentDom.insertBefore(newChild.toDom(opts), ref);
7841
+ delete(k) {
7842
+ if (this.items.has(k)) {
7843
+ const newOrder = this.order.delete(this.order.indexOf(k));
7844
+ return this._clonish(this.items.delete(k), newOrder);
7843
7845
  }
7846
+ return this;
7844
7847
  }
7845
- for (let i = oldChilds.length - 1;i >= 0; i--) {
7846
- if (!used[i] && domNodes[i].parentNode === parentDom) {
7847
- parentDom.removeChild(domNodes[i]);
7848
+ moveKeyBeforeKey(k1, k2) {
7849
+ const { order } = this;
7850
+ return this.moveKeyIndexToIndex(order.indexOf(k1), order.indexOf(k2), 0);
7851
+ }
7852
+ moveKeyAfterKey(k1, k2) {
7853
+ const { order } = this;
7854
+ return this.moveKeyIndexToIndex(order.indexOf(k1), order.indexOf(k2), 1);
7855
+ }
7856
+ moveKeyIndexToIndex(source, target, offset) {
7857
+ if (source === -1 || target === -1 || source === target) {
7858
+ return this;
7848
7859
  }
7860
+ const { order } = this;
7861
+ const newPos = target + offset;
7862
+ const oldPos = newPos < source ? source + 1 : source;
7863
+ const newOrder = order.insert(newPos, order.get(source)).delete(oldPos);
7864
+ return this._clonish(this.items, newOrder);
7849
7865
  }
7850
7866
  }
7851
- var renderCache = new WeakMap;
7852
- function render(vnode, container, options) {
7853
- const cached = renderCache.get(container);
7854
- const isFragment = vnode instanceof VFragment;
7855
- if (cached && cached.vnode instanceof VFragment === isFragment) {
7856
- const oldDom = isFragment ? container : cached.dom;
7857
- const newDom = morphNode(oldDom, cached.vnode, vnode, options);
7858
- renderCache.set(container, { vnode, dom: isFragment ? container : newDom });
7859
- return newDom;
7867
+ var klistCoercer = (_) => null;
7868
+
7869
+ class CheckTypeKList {
7870
+ isValid(v) {
7871
+ return v instanceof KList;
7860
7872
  }
7861
- renderCache.delete(container);
7862
- const domNode = vnode.toDom(options);
7863
- container.replaceChildren(domNode);
7864
- renderCache.set(container, { vnode, dom: isFragment ? container : domNode });
7865
- return domNode;
7866
- }
7867
- function h(tagName, properties, children) {
7868
- const tag = tagName.toUpperCase();
7869
- const props = {};
7870
- let key, namespace;
7871
- if (properties) {
7872
- for (const propName in properties) {
7873
- const propVal = properties[propName];
7874
- switch (propName) {
7875
- case "key":
7876
- key = propVal;
7877
- break;
7878
- case "namespace":
7879
- namespace = propVal;
7880
- break;
7881
- case "class":
7882
- props.className = propVal;
7883
- break;
7884
- case "for":
7885
- props.htmlFor = propVal;
7886
- break;
7887
- default:
7888
- props[propName] = isHtmlAttribute(propName) ? String(propVal) : propVal;
7889
- }
7890
- }
7873
+ getMessage(_v) {
7874
+ return "KList expected";
7891
7875
  }
7892
- const normalizedChildren = [];
7893
- addChild(normalizedChildren, children);
7894
- return new VNode2(tag, props, normalizedChildren, key, namespace);
7895
7876
  }
7877
+ var CHECK_TYPE_KLIST = new CheckTypeKList;
7896
7878
 
7879
+ class FieldKList extends Field {
7880
+ constructor(name, defaultValue = new KList) {
7881
+ super("KList", name, CHECK_TYPE_KLIST, klistCoercer, defaultValue);
7882
+ }
7883
+ extendProtoForType(proto, uname) {
7884
+ extendProtoForKeyed(proto, this.name, uname);
7885
+ const { name } = this;
7886
+ extendProtoForKeyed(proto, name, uname);
7887
+ proto[`pushIn${uname}`] = function(v) {
7888
+ return this.set(name, this.get(name).push(v));
7889
+ };
7890
+ }
7891
+ }
7892
+ fieldsByClass.set(KList, FieldKList);
7893
+ seqInfoByClass.set(KList, (seq, visit) => {
7894
+ for (const k of seq.order)
7895
+ visit(k, seq.items.get(k), "data-sk");
7896
+ });
7897
7897
  // index.js
7898
7898
  var css = String.raw;
7899
7899
  var html = String.raw;
7900
- function macro(defaults, rawView) {
7901
- return new Macro(defaults, rawView);
7902
- }
7903
- var toNode = (nodeOrSelector) => typeof nodeOrSelector === "string" ? document.querySelector(nodeOrSelector) : nodeOrSelector;
7900
+ var macro = (defaults, rawView) => new Macro(defaults, rawView);
7904
7901
  function tutuca(nodeOrSelector) {
7905
- const rootNode = toNode(nodeOrSelector);
7902
+ const rootNode = typeof nodeOrSelector === "string" ? document.querySelector(nodeOrSelector) : nodeOrSelector;
7906
7903
  const comps = new Components;
7907
- const fragment = (childs) => new VFragment(childs);
7908
- const comment = (text) => new VComment(text);
7909
- const ropts = { document };
7910
- const render1 = (vnode, cont) => render(vnode, cont, ropts);
7911
- const renderer = new Renderer(comps, h, fragment, comment, render1);
7912
- return new App(rootNode, render1, comps, renderer, ParseContext);
7904
+ const renderer = new Renderer(comps);
7905
+ return new App(rootNode, comps, renderer, ParseContext);
7913
7906
  }
7914
7907
 
7915
7908
  // extra.js
@@ -7927,9 +7920,8 @@ async function compileClassesToStyleText(app, compileClasses, extraCSSClasses, C
7927
7920
  for (const Comp of app.comps.byId.values()) {
7928
7921
  for (const key in Comp.views) {
7929
7922
  const view = Comp.views[key];
7930
- for (const name of view.ctx.classes) {
7923
+ for (const name of view.ctx.classes)
7931
7924
  classes.add(name);
7932
- }
7933
7925
  }
7934
7926
  }
7935
7927
  return await compileClasses(Array.from(classes));
@@ -8155,6 +8147,7 @@ class LintParseContext extends ParseContext {
8155
8147
  this.attrs.push({ attrs, wrapperAttrs, textChild });
8156
8148
  }
8157
8149
  }
8150
+
8158
8151
  // dev.js
8159
8152
  class LintClassCollectorCtx extends ParseCtxClassSetCollector {
8160
8153
  constructor(...args) {