tutuca 0.9.66 → 0.9.68

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.
@@ -1172,40 +1172,67 @@ class RequestHandler {
1172
1172
  }
1173
1173
 
1174
1174
  // src/vdom.js
1175
- var isHtmlAttribute = (propName) => propName[4] === "-" && (propName[0] === "d" || propName[0] === "a");
1176
1175
  var HTML_NS = "http://www.w3.org/1999/xhtml";
1176
+ var SVG_NS = "http://www.w3.org/2000/svg";
1177
+ var MATH_NS = "http://www.w3.org/1998/Math/MathML";
1177
1178
  var isNamespaced = (node) => {
1178
1179
  const ns = node.namespaceURI;
1179
1180
  return ns !== null && ns !== HTML_NS;
1180
1181
  };
1181
- function applyProperties(node, props, previous) {
1182
+ var isForeignObject = (tag) => tag.length === 13 && tag.toLowerCase() === "foreignobject";
1183
+ var effectiveNs = (vnode, opts) => vnode.namespace ?? opts.namespace ?? null;
1184
+ function childOpts(vnode, ns, opts) {
1185
+ const target = ns === SVG_NS && isForeignObject(vnode.tag) ? null : ns;
1186
+ return target === (opts.namespace ?? null) ? opts : { ...opts, namespace: target };
1187
+ }
1188
+ var NEVER_ASSIGN = new Set([
1189
+ "width",
1190
+ "height",
1191
+ "href",
1192
+ "list",
1193
+ "form",
1194
+ "tabIndex",
1195
+ "download",
1196
+ "rowSpan",
1197
+ "colSpan",
1198
+ "role",
1199
+ "popover"
1200
+ ]);
1201
+ function applyProperties(node, props) {
1182
1202
  const namespaced = isNamespaced(node);
1183
- for (const propName in props) {
1184
- const propValue = props[propName];
1185
- if (propValue === undefined)
1186
- removeProperty(node, propName, previous);
1187
- else if (propName === "dangerouslySetInnerHTML")
1188
- node.innerHTML = propValue.__html ?? "";
1189
- else if (propName === "className")
1190
- node.setAttribute("class", propValue);
1191
- else if (namespaced || isHtmlAttribute(propName))
1192
- node.setAttribute(propName, propValue);
1193
- else
1194
- node[propName] = propValue;
1195
- }
1196
- }
1197
- function removeProperty(node, propName, previous) {
1198
- const previousValue = previous[propName];
1199
- if (propName === "dangerouslySetInnerHTML")
1200
- node.replaceChildren();
1201
- else if (propName === "className")
1202
- node.removeAttribute("class");
1203
- else if (propName === "htmlFor")
1204
- node.removeAttribute("for");
1205
- else if (isNamespaced(node) || typeof previousValue === "string" || isHtmlAttribute(propName))
1206
- node.removeAttribute(propName);
1203
+ for (const name in props)
1204
+ setProp(node, name, props[name], namespaced);
1205
+ }
1206
+ function setProp(node, name, value, namespaced) {
1207
+ if (name === "dangerouslySetInnerHTML") {
1208
+ if (value === undefined)
1209
+ node.replaceChildren();
1210
+ else {
1211
+ const html = value.__html ?? "";
1212
+ if (html !== node.innerHTML)
1213
+ node.innerHTML = html;
1214
+ }
1215
+ return;
1216
+ }
1217
+ if (typeof value === "function")
1218
+ return;
1219
+ if (!namespaced && !NEVER_ASSIGN.has(name) && name in node) {
1220
+ try {
1221
+ node[name] = value == null ? "" : value;
1222
+ return;
1223
+ } catch {}
1224
+ }
1225
+ if (value == null || value === false && name[4] !== "-")
1226
+ node.removeAttribute(name);
1207
1227
  else
1208
- node[propName] = null;
1228
+ node.setAttribute(name, value);
1229
+ }
1230
+ function applyValueLast(node, value) {
1231
+ if (node.tagName === "PROGRESS" && (value == null || value === 0)) {
1232
+ node.removeAttribute("value");
1233
+ } else {
1234
+ setProp(node, "value", value, isNamespaced(node));
1235
+ }
1209
1236
  }
1210
1237
 
1211
1238
  class VBase {
@@ -1325,15 +1352,23 @@ class VNode extends VBase {
1325
1352
  }
1326
1353
  toDom(opts) {
1327
1354
  const doc = opts.document;
1328
- const node = this.namespace === null ? doc.createElement(this.tag) : doc.createElementNS(this.namespace, this.tag);
1329
- if (this.tag === "SELECT" && "value" in this.attrs) {
1330
- const { value, ...rest } = this.attrs;
1331
- applyProperties(node, rest, {});
1332
- appendChildNodes(node, this.childs, opts);
1333
- applyProperties(node, { value }, {});
1355
+ const ns = effectiveNs(this, opts);
1356
+ const tag = ns !== null && this.tag === this.tag.toUpperCase() ? this.tag.toLowerCase() : this.tag;
1357
+ const attrs = this.attrs;
1358
+ const createOpts = attrs.is != null ? { is: attrs.is } : undefined;
1359
+ const node = ns === null ? doc.createElement(tag, createOpts) : doc.createElementNS(ns, tag, createOpts);
1360
+ const cOpts = childOpts(this, ns, opts);
1361
+ if ("value" in attrs || "checked" in attrs) {
1362
+ const { value, checked, ...rest } = attrs;
1363
+ applyProperties(node, rest);
1364
+ appendChildNodes(node, this.childs, cOpts);
1365
+ if (value !== undefined)
1366
+ applyValueLast(node, value);
1367
+ if (checked !== undefined)
1368
+ setProp(node, "checked", checked, false);
1334
1369
  } else {
1335
- applyProperties(node, this.attrs, {});
1336
- appendChildNodes(node, this.childs, opts);
1370
+ applyProperties(node, attrs);
1371
+ appendChildNodes(node, this.childs, cOpts);
1337
1372
  }
1338
1373
  return node;
1339
1374
  }
@@ -1370,18 +1405,37 @@ function morphNode(domNode, source, target, opts) {
1370
1405
  }
1371
1406
  if (type === 1 && source.isSameKind(target)) {
1372
1407
  const propsDiff = diffProps(source.attrs, target.attrs);
1373
- const isSelect = source.tag === "SELECT";
1408
+ let pendingValue;
1409
+ let pendingChecked;
1410
+ let applyValue = false;
1411
+ let applyChecked = false;
1374
1412
  if (propsDiff) {
1375
- if (isSelect && "value" in propsDiff) {
1376
- const { value: _v, ...rest } = propsDiff;
1377
- applyProperties(domNode, rest, source.attrs);
1413
+ if ("value" in propsDiff || "checked" in propsDiff) {
1414
+ const { value, checked, ...rest } = propsDiff;
1415
+ applyProperties(domNode, rest);
1416
+ if ("value" in propsDiff) {
1417
+ pendingValue = value;
1418
+ applyValue = true;
1419
+ }
1420
+ if ("checked" in propsDiff) {
1421
+ pendingChecked = checked;
1422
+ applyChecked = true;
1423
+ }
1378
1424
  } else
1379
- applyProperties(domNode, propsDiff, source.attrs);
1425
+ applyProperties(domNode, propsDiff);
1426
+ }
1427
+ if (!target.attrs.dangerouslySetInnerHTML) {
1428
+ const ns = effectiveNs(target, opts);
1429
+ morphChildren(domNode, source.childs, target.childs, childOpts(target, ns, opts));
1430
+ }
1431
+ if (!applyValue && source.tag === "SELECT" && target.attrs.value !== undefined) {
1432
+ pendingValue = target.attrs.value;
1433
+ applyValue = true;
1380
1434
  }
1381
- if (!target.attrs.dangerouslySetInnerHTML)
1382
- morphChildren(domNode, source.childs, target.childs, opts);
1383
- if (isSelect && target.attrs.value !== undefined)
1384
- applyProperties(domNode, { value: target.attrs.value }, source.attrs);
1435
+ if (applyValue)
1436
+ applyValueLast(domNode, pendingValue);
1437
+ if (applyChecked)
1438
+ setProp(domNode, "checked", pendingChecked, false);
1385
1439
  return domNode;
1386
1440
  }
1387
1441
  if (type === 11) {
@@ -1477,26 +1531,26 @@ function h(tagName, properties, children, namespace) {
1477
1531
  if (properties) {
1478
1532
  for (const propName in properties) {
1479
1533
  const propVal = properties[propName];
1480
- switch (propName) {
1481
- case "key":
1482
- key = propVal;
1483
- break;
1484
- case "namespace":
1485
- namespace = namespace ?? propVal;
1486
- break;
1487
- case "class":
1488
- props.className = propVal;
1489
- break;
1490
- case "for":
1491
- props.htmlFor = propVal;
1492
- break;
1493
- default:
1494
- props[propName] = isHtmlAttribute(propName) ? String(propVal) : propVal;
1495
- }
1534
+ if (propName === "key")
1535
+ key = propVal;
1536
+ else if (propName === "namespace")
1537
+ namespace = namespace ?? propVal;
1538
+ else
1539
+ props[propName] = propVal;
1540
+ }
1541
+ }
1542
+ if (namespace == null) {
1543
+ const lower = tagName.toLowerCase();
1544
+ if (lower === "svg") {
1545
+ namespace = SVG_NS;
1546
+ tagName = "svg";
1547
+ } else if (lower === "math") {
1548
+ namespace = MATH_NS;
1549
+ tagName = "math";
1496
1550
  }
1497
1551
  }
1498
1552
  const c = tagName.charCodeAt(0);
1499
- const tag = namespace == null && c >= 97 && c <= 122 ? tagName.toUpperCase() : tagName;
1553
+ const tag = namespace == null && c >= 97 && c <= 122 && tagName === tagName.toLowerCase() ? tagName.toUpperCase() : tagName;
1500
1554
  const normalizedChildren = [];
1501
1555
  addChild(normalizedChildren, children);
1502
1556
  return new VNode(tag, props, normalizedChildren, key, namespace);
@@ -3798,6 +3852,10 @@ function check(_app) {
3798
3852
  async function test(_opts) {
3799
3853
  return null;
3800
3854
  }
3855
+ function collectIterBindings() {
3856
+ console.warn("collectIterBindings is a no-op in the core tutuca build; use the tutuca-dev build for a functional implementation");
3857
+ return [];
3858
+ }
3801
3859
  function tutuca(nodeOrSelector) {
3802
3860
  const rootNode = typeof nodeOrSelector === "string" ? document.querySelector(nodeOrSelector) : nodeOrSelector;
3803
3861
  const comps = new Components;
@@ -3814,6 +3872,7 @@ export {
3814
3872
  html,
3815
3873
  css,
3816
3874
  component,
3875
+ collectIterBindings,
3817
3876
  check,
3818
3877
  SEQ_INFO,
3819
3878
  ParseContext,
package/dist/tutuca.js CHANGED
@@ -5545,40 +5545,67 @@ class RequestHandler {
5545
5545
  }
5546
5546
 
5547
5547
  // src/vdom.js
5548
- var isHtmlAttribute = (propName) => propName[4] === "-" && (propName[0] === "d" || propName[0] === "a");
5549
5548
  var HTML_NS = "http://www.w3.org/1999/xhtml";
5549
+ var SVG_NS = "http://www.w3.org/2000/svg";
5550
+ var MATH_NS = "http://www.w3.org/1998/Math/MathML";
5550
5551
  var isNamespaced = (node) => {
5551
5552
  const ns = node.namespaceURI;
5552
5553
  return ns !== null && ns !== HTML_NS;
5553
5554
  };
5554
- function applyProperties(node, props, previous) {
5555
+ var isForeignObject = (tag) => tag.length === 13 && tag.toLowerCase() === "foreignobject";
5556
+ var effectiveNs = (vnode, opts) => vnode.namespace ?? opts.namespace ?? null;
5557
+ function childOpts(vnode, ns, opts) {
5558
+ const target = ns === SVG_NS && isForeignObject(vnode.tag) ? null : ns;
5559
+ return target === (opts.namespace ?? null) ? opts : { ...opts, namespace: target };
5560
+ }
5561
+ var NEVER_ASSIGN = new Set([
5562
+ "width",
5563
+ "height",
5564
+ "href",
5565
+ "list",
5566
+ "form",
5567
+ "tabIndex",
5568
+ "download",
5569
+ "rowSpan",
5570
+ "colSpan",
5571
+ "role",
5572
+ "popover"
5573
+ ]);
5574
+ function applyProperties(node, props) {
5555
5575
  const namespaced = isNamespaced(node);
5556
- for (const propName in props) {
5557
- const propValue = props[propName];
5558
- if (propValue === undefined)
5559
- removeProperty(node, propName, previous);
5560
- else if (propName === "dangerouslySetInnerHTML")
5561
- node.innerHTML = propValue.__html ?? "";
5562
- else if (propName === "className")
5563
- node.setAttribute("class", propValue);
5564
- else if (namespaced || isHtmlAttribute(propName))
5565
- node.setAttribute(propName, propValue);
5566
- else
5567
- node[propName] = propValue;
5568
- }
5569
- }
5570
- function removeProperty(node, propName, previous) {
5571
- const previousValue = previous[propName];
5572
- if (propName === "dangerouslySetInnerHTML")
5573
- node.replaceChildren();
5574
- else if (propName === "className")
5575
- node.removeAttribute("class");
5576
- else if (propName === "htmlFor")
5577
- node.removeAttribute("for");
5578
- else if (isNamespaced(node) || typeof previousValue === "string" || isHtmlAttribute(propName))
5579
- node.removeAttribute(propName);
5576
+ for (const name in props)
5577
+ setProp2(node, name, props[name], namespaced);
5578
+ }
5579
+ function setProp2(node, name, value, namespaced) {
5580
+ if (name === "dangerouslySetInnerHTML") {
5581
+ if (value === undefined)
5582
+ node.replaceChildren();
5583
+ else {
5584
+ const html = value.__html ?? "";
5585
+ if (html !== node.innerHTML)
5586
+ node.innerHTML = html;
5587
+ }
5588
+ return;
5589
+ }
5590
+ if (typeof value === "function")
5591
+ return;
5592
+ if (!namespaced && !NEVER_ASSIGN.has(name) && name in node) {
5593
+ try {
5594
+ node[name] = value == null ? "" : value;
5595
+ return;
5596
+ } catch {}
5597
+ }
5598
+ if (value == null || value === false && name[4] !== "-")
5599
+ node.removeAttribute(name);
5580
5600
  else
5581
- node[propName] = null;
5601
+ node.setAttribute(name, value);
5602
+ }
5603
+ function applyValueLast(node, value) {
5604
+ if (node.tagName === "PROGRESS" && (value == null || value === 0)) {
5605
+ node.removeAttribute("value");
5606
+ } else {
5607
+ setProp2(node, "value", value, isNamespaced(node));
5608
+ }
5582
5609
  }
5583
5610
 
5584
5611
  class VBase {
@@ -5698,15 +5725,23 @@ class VNode2 extends VBase {
5698
5725
  }
5699
5726
  toDom(opts) {
5700
5727
  const doc = opts.document;
5701
- const node = this.namespace === null ? doc.createElement(this.tag) : doc.createElementNS(this.namespace, this.tag);
5702
- if (this.tag === "SELECT" && "value" in this.attrs) {
5703
- const { value, ...rest } = this.attrs;
5704
- applyProperties(node, rest, {});
5705
- appendChildNodes(node, this.childs, opts);
5706
- applyProperties(node, { value }, {});
5728
+ const ns = effectiveNs(this, opts);
5729
+ const tag = ns !== null && this.tag === this.tag.toUpperCase() ? this.tag.toLowerCase() : this.tag;
5730
+ const attrs = this.attrs;
5731
+ const createOpts = attrs.is != null ? { is: attrs.is } : undefined;
5732
+ const node = ns === null ? doc.createElement(tag, createOpts) : doc.createElementNS(ns, tag, createOpts);
5733
+ const cOpts = childOpts(this, ns, opts);
5734
+ if ("value" in attrs || "checked" in attrs) {
5735
+ const { value, checked, ...rest } = attrs;
5736
+ applyProperties(node, rest);
5737
+ appendChildNodes(node, this.childs, cOpts);
5738
+ if (value !== undefined)
5739
+ applyValueLast(node, value);
5740
+ if (checked !== undefined)
5741
+ setProp2(node, "checked", checked, false);
5707
5742
  } else {
5708
- applyProperties(node, this.attrs, {});
5709
- appendChildNodes(node, this.childs, opts);
5743
+ applyProperties(node, attrs);
5744
+ appendChildNodes(node, this.childs, cOpts);
5710
5745
  }
5711
5746
  return node;
5712
5747
  }
@@ -5743,18 +5778,37 @@ function morphNode(domNode, source, target, opts) {
5743
5778
  }
5744
5779
  if (type === 1 && source.isSameKind(target)) {
5745
5780
  const propsDiff = diffProps(source.attrs, target.attrs);
5746
- const isSelect = source.tag === "SELECT";
5781
+ let pendingValue;
5782
+ let pendingChecked;
5783
+ let applyValue = false;
5784
+ let applyChecked = false;
5747
5785
  if (propsDiff) {
5748
- if (isSelect && "value" in propsDiff) {
5749
- const { value: _v, ...rest } = propsDiff;
5750
- applyProperties(domNode, rest, source.attrs);
5786
+ if ("value" in propsDiff || "checked" in propsDiff) {
5787
+ const { value, checked, ...rest } = propsDiff;
5788
+ applyProperties(domNode, rest);
5789
+ if ("value" in propsDiff) {
5790
+ pendingValue = value;
5791
+ applyValue = true;
5792
+ }
5793
+ if ("checked" in propsDiff) {
5794
+ pendingChecked = checked;
5795
+ applyChecked = true;
5796
+ }
5751
5797
  } else
5752
- applyProperties(domNode, propsDiff, source.attrs);
5798
+ applyProperties(domNode, propsDiff);
5799
+ }
5800
+ if (!target.attrs.dangerouslySetInnerHTML) {
5801
+ const ns = effectiveNs(target, opts);
5802
+ morphChildren(domNode, source.childs, target.childs, childOpts(target, ns, opts));
5803
+ }
5804
+ if (!applyValue && source.tag === "SELECT" && target.attrs.value !== undefined) {
5805
+ pendingValue = target.attrs.value;
5806
+ applyValue = true;
5753
5807
  }
5754
- if (!target.attrs.dangerouslySetInnerHTML)
5755
- morphChildren(domNode, source.childs, target.childs, opts);
5756
- if (isSelect && target.attrs.value !== undefined)
5757
- applyProperties(domNode, { value: target.attrs.value }, source.attrs);
5808
+ if (applyValue)
5809
+ applyValueLast(domNode, pendingValue);
5810
+ if (applyChecked)
5811
+ setProp2(domNode, "checked", pendingChecked, false);
5758
5812
  return domNode;
5759
5813
  }
5760
5814
  if (type === 11) {
@@ -5850,26 +5904,26 @@ function h(tagName, properties, children, namespace) {
5850
5904
  if (properties) {
5851
5905
  for (const propName in properties) {
5852
5906
  const propVal = properties[propName];
5853
- switch (propName) {
5854
- case "key":
5855
- key = propVal;
5856
- break;
5857
- case "namespace":
5858
- namespace = namespace ?? propVal;
5859
- break;
5860
- case "class":
5861
- props.className = propVal;
5862
- break;
5863
- case "for":
5864
- props.htmlFor = propVal;
5865
- break;
5866
- default:
5867
- props[propName] = isHtmlAttribute(propName) ? String(propVal) : propVal;
5868
- }
5907
+ if (propName === "key")
5908
+ key = propVal;
5909
+ else if (propName === "namespace")
5910
+ namespace = namespace ?? propVal;
5911
+ else
5912
+ props[propName] = propVal;
5913
+ }
5914
+ }
5915
+ if (namespace == null) {
5916
+ const lower = tagName.toLowerCase();
5917
+ if (lower === "svg") {
5918
+ namespace = SVG_NS;
5919
+ tagName = "svg";
5920
+ } else if (lower === "math") {
5921
+ namespace = MATH_NS;
5922
+ tagName = "math";
5869
5923
  }
5870
5924
  }
5871
5925
  const c = tagName.charCodeAt(0);
5872
- const tag = namespace == null && c >= 97 && c <= 122 ? tagName.toUpperCase() : tagName;
5926
+ const tag = namespace == null && c >= 97 && c <= 122 && tagName === tagName.toLowerCase() ? tagName.toUpperCase() : tagName;
5873
5927
  const normalizedChildren = [];
5874
5928
  addChild(normalizedChildren, children);
5875
5929
  return new VNode2(tag, props, normalizedChildren, key, namespace);
@@ -8156,6 +8210,10 @@ function check(_app) {
8156
8210
  async function test(_opts) {
8157
8211
  return null;
8158
8212
  }
8213
+ function collectIterBindings() {
8214
+ console.warn("collectIterBindings is a no-op in the core tutuca build; use the tutuca-dev build for a functional implementation");
8215
+ return [];
8216
+ }
8159
8217
  function tutuca(nodeOrSelector) {
8160
8218
  const rootNode = typeof nodeOrSelector === "string" ? document.querySelector(nodeOrSelector) : nodeOrSelector;
8161
8219
  const comps = new Components;
@@ -8206,6 +8264,7 @@ export {
8206
8264
  fromJS,
8207
8265
  css,
8208
8266
  component,
8267
+ collectIterBindings,
8209
8268
  check,
8210
8269
  Stack,
8211
8270
  Set2 as Set,