tutuca 0.9.67 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tutuca",
3
- "version": "0.9.67",
3
+ "version": "0.9.68",
4
4
  "type": "module",
5
5
  "description": "Zero-dependency SPA framework with immutable state and virtual DOM",
6
6
  "main": "./dist/tutuca.js",
@@ -1173,10 +1173,18 @@ class RequestHandler {
1173
1173
 
1174
1174
  // src/vdom.js
1175
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";
1176
1178
  var isNamespaced = (node) => {
1177
1179
  const ns = node.namespaceURI;
1178
1180
  return ns !== null && ns !== HTML_NS;
1179
1181
  };
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
+ }
1180
1188
  var NEVER_ASSIGN = new Set([
1181
1189
  "width",
1182
1190
  "height",
@@ -1190,7 +1198,7 @@ var NEVER_ASSIGN = new Set([
1190
1198
  "role",
1191
1199
  "popover"
1192
1200
  ]);
1193
- function applyProperties(node, props, _previous) {
1201
+ function applyProperties(node, props) {
1194
1202
  const namespaced = isNamespaced(node);
1195
1203
  for (const name in props)
1196
1204
  setProp(node, name, props[name], namespaced);
@@ -1199,8 +1207,11 @@ function setProp(node, name, value, namespaced) {
1199
1207
  if (name === "dangerouslySetInnerHTML") {
1200
1208
  if (value === undefined)
1201
1209
  node.replaceChildren();
1202
- else
1203
- node.innerHTML = value.__html ?? "";
1210
+ else {
1211
+ const html = value.__html ?? "";
1212
+ if (html !== node.innerHTML)
1213
+ node.innerHTML = html;
1214
+ }
1204
1215
  return;
1205
1216
  }
1206
1217
  if (typeof value === "function")
@@ -1216,6 +1227,13 @@ function setProp(node, name, value, namespaced) {
1216
1227
  else
1217
1228
  node.setAttribute(name, value);
1218
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
+ }
1236
+ }
1219
1237
 
1220
1238
  class VBase {
1221
1239
  }
@@ -1334,15 +1352,23 @@ class VNode extends VBase {
1334
1352
  }
1335
1353
  toDom(opts) {
1336
1354
  const doc = opts.document;
1337
- const node = this.namespace === null ? doc.createElement(this.tag) : doc.createElementNS(this.namespace, this.tag);
1338
- if (this.tag === "SELECT" && "value" in this.attrs) {
1339
- const { value, ...rest } = this.attrs;
1340
- applyProperties(node, rest, {});
1341
- appendChildNodes(node, this.childs, opts);
1342
- 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);
1343
1369
  } else {
1344
- applyProperties(node, this.attrs, {});
1345
- appendChildNodes(node, this.childs, opts);
1370
+ applyProperties(node, attrs);
1371
+ appendChildNodes(node, this.childs, cOpts);
1346
1372
  }
1347
1373
  return node;
1348
1374
  }
@@ -1379,18 +1405,37 @@ function morphNode(domNode, source, target, opts) {
1379
1405
  }
1380
1406
  if (type === 1 && source.isSameKind(target)) {
1381
1407
  const propsDiff = diffProps(source.attrs, target.attrs);
1382
- const isSelect = source.tag === "SELECT";
1408
+ let pendingValue;
1409
+ let pendingChecked;
1410
+ let applyValue = false;
1411
+ let applyChecked = false;
1383
1412
  if (propsDiff) {
1384
- if (isSelect && "value" in propsDiff) {
1385
- const { value: _v, ...rest } = propsDiff;
1386
- 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
+ }
1387
1424
  } else
1388
- 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));
1389
1430
  }
1390
- if (!target.attrs.dangerouslySetInnerHTML)
1391
- morphChildren(domNode, source.childs, target.childs, opts);
1392
- if (isSelect && target.attrs.value !== undefined)
1393
- applyProperties(domNode, { value: target.attrs.value }, source.attrs);
1431
+ if (!applyValue && source.tag === "SELECT" && target.attrs.value !== undefined) {
1432
+ pendingValue = target.attrs.value;
1433
+ applyValue = true;
1434
+ }
1435
+ if (applyValue)
1436
+ applyValueLast(domNode, pendingValue);
1437
+ if (applyChecked)
1438
+ setProp(domNode, "checked", pendingChecked, false);
1394
1439
  return domNode;
1395
1440
  }
1396
1441
  if (type === 11) {
@@ -1494,8 +1539,18 @@ function h(tagName, properties, children, namespace) {
1494
1539
  props[propName] = propVal;
1495
1540
  }
1496
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";
1550
+ }
1551
+ }
1497
1552
  const c = tagName.charCodeAt(0);
1498
- 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;
1499
1554
  const normalizedChildren = [];
1500
1555
  addChild(normalizedChildren, children);
1501
1556
  return new VNode(tag, props, normalizedChildren, key, namespace);