@nisli/core 0.57.0 → 0.57.1

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/dist/index.js CHANGED
@@ -1319,8 +1319,10 @@ function html(strings, ...values) {
1319
1319
  mounted = true;
1320
1320
  const template = parseTemplate(strings, values.length);
1321
1321
  const fragment = template.content.cloneNode(true);
1322
- processNode(fragment, values, bindings, disposers);
1322
+ const afterMount = [];
1323
+ processNode(fragment, values, bindings, disposers, afterMount);
1323
1324
  host.appendChild(fragment);
1325
+ for (const sync of afterMount) sync();
1324
1326
  },
1325
1327
  dispose() {
1326
1328
  for (const d of disposers) {
@@ -1343,10 +1345,11 @@ function html(strings, ...values) {
1343
1345
  }
1344
1346
  };
1345
1347
  }
1346
- function processNode(node, values, bindings, disposers) {
1348
+ function processNode(node, values, bindings, disposers, afterMount) {
1349
+ let afterChildren;
1347
1350
  if (node.nodeType === Node.ELEMENT_NODE) {
1348
1351
  const el2 = node;
1349
- processAttributes(el2, values, bindings, disposers);
1352
+ afterChildren = processAttributes(el2, values, bindings, disposers, afterMount);
1350
1353
  }
1351
1354
  if (node.nodeType === Node.COMMENT_NODE) {
1352
1355
  const comment = node;
@@ -1360,11 +1363,13 @@ function processNode(node, values, bindings, disposers) {
1360
1363
  }
1361
1364
  const children2 = [...node.childNodes];
1362
1365
  for (const child of children2) {
1363
- processNode(child, values, bindings, disposers);
1366
+ processNode(child, values, bindings, disposers, afterMount);
1364
1367
  }
1368
+ if (afterChildren) for (const bind of afterChildren) bind();
1365
1369
  }
1366
- function processAttributes(el2, values, bindings, disposers) {
1370
+ function processAttributes(el2, values, bindings, disposers, afterMount) {
1367
1371
  const attrsToRemove = [];
1372
+ let afterChildren;
1368
1373
  for (const attr of [...el2.attributes]) {
1369
1374
  const name = attr.name;
1370
1375
  const attrValue = attr.value;
@@ -1423,8 +1428,9 @@ function processAttributes(el2, values, bindings, disposers) {
1423
1428
  const markers = [...attrValue.matchAll(/<!--bk-(\d+)-->/g)];
1424
1429
  if (markers.length) {
1425
1430
  const first = markers[0];
1431
+ let value;
1426
1432
  if (markers.length === 1 && first && attrValue === first[0]) {
1427
- bindAttribute(el2, name, values[Number(first[1])], bindings, disposers);
1433
+ value = values[Number(first[1])];
1428
1434
  } else {
1429
1435
  const resolve = () => attrValue.replace(/<!--bk-(\d+)-->/g, (_, i) => {
1430
1436
  const v = values[Number(i)];
@@ -1432,7 +1438,12 @@ function processAttributes(el2, values, bindings, disposers) {
1432
1438
  return raw2 == null || raw2 === false ? "" : String(raw2);
1433
1439
  });
1434
1440
  const hasSignals = markers.some((m) => isSignal(values[Number(m[1])]));
1435
- bindAttribute(el2, name, hasSignals ? computed(resolve) : resolve(), bindings, disposers);
1441
+ value = hasSignals ? computed(resolve) : resolve();
1442
+ }
1443
+ if (nativeFormProperty(el2, name)) {
1444
+ (afterChildren ??= []).push(() => bindAttribute(el2, name, value, bindings, disposers, afterMount));
1445
+ } else {
1446
+ bindAttribute(el2, name, value, bindings, disposers, afterMount);
1436
1447
  }
1437
1448
  }
1438
1449
  continue;
@@ -1441,6 +1452,7 @@ function processAttributes(el2, values, bindings, disposers) {
1441
1452
  for (const name of attrsToRemove) {
1442
1453
  el2.removeAttribute(name);
1443
1454
  }
1455
+ return afterChildren;
1444
1456
  }
1445
1457
  function mountFactoryResult(factory) {
1446
1458
  const el2 = document.createElement(factory.tagName);
@@ -1639,7 +1651,7 @@ function replaceMarkerWithBinding(comment, value, bindings, disposers) {
1639
1651
  parent.replaceChild(textNode, comment);
1640
1652
  }
1641
1653
  }
1642
- function bindAttribute(el2, name, value, bindings, disposers) {
1654
+ function bindAttribute(el2, name, value, bindings, disposers, afterMount) {
1643
1655
  if (name === "class") {
1644
1656
  bindClassAttribute(el2, value, bindings, disposers);
1645
1657
  return;
@@ -1660,32 +1672,69 @@ function bindAttribute(el2, name, value, bindings, disposers) {
1660
1672
  }
1661
1673
  return;
1662
1674
  }
1663
- bindPlainAttribute(el2, name, value, bindings, disposers);
1675
+ bindPlainAttribute(el2, name, value, bindings, disposers, afterMount);
1664
1676
  }
1665
- function bindPlainAttribute(el2, name, value, bindings, disposers) {
1677
+ function bindPlainAttribute(el2, name, value, bindings, disposers, afterMount) {
1678
+ const property = nativeFormProperty(el2, name);
1679
+ let current;
1680
+ const apply = (v) => {
1681
+ current = v;
1682
+ if (v == null || v === false) {
1683
+ el2.removeAttribute(name);
1684
+ } else {
1685
+ el2.setAttribute(name, v === true ? "" : String(v));
1686
+ }
1687
+ if (property) syncFormProperty(el2, property, v);
1688
+ };
1666
1689
  if (isSignal(value)) {
1667
1690
  const binding = { type: "attribute", element: el2, name };
1668
1691
  bindings.push(binding);
1669
- const dispose = effect(() => {
1670
- const v = value.value;
1671
- if (v == null || v === false) {
1672
- el2.removeAttribute(name);
1673
- } else if (v === true) {
1674
- el2.setAttribute(name, "");
1675
- } else {
1676
- el2.setAttribute(name, String(v));
1677
- }
1678
- });
1692
+ const dispose = effect(() => apply(value.value));
1679
1693
  binding.dispose = dispose;
1680
1694
  disposers.push(dispose);
1681
1695
  } else {
1682
- if (value == null || value === false) {
1683
- el2.removeAttribute(name);
1684
- } else if (value === true) {
1685
- el2.setAttribute(name, "");
1686
- } else {
1687
- el2.setAttribute(name, String(value));
1688
- }
1696
+ apply(value);
1697
+ }
1698
+ if (property === "value" && el2.localName === "select") {
1699
+ let active = true;
1700
+ const sync = () => {
1701
+ if (active) syncFormProperty(el2, "value", current);
1702
+ };
1703
+ const observer = new MutationObserver(sync);
1704
+ observer.observe(el2, {
1705
+ childList: true,
1706
+ subtree: true,
1707
+ characterData: true,
1708
+ attributes: true,
1709
+ attributeFilter: ["value", "selected"]
1710
+ });
1711
+ disposers.push(() => {
1712
+ active = false;
1713
+ observer.disconnect();
1714
+ });
1715
+ afterMount.push(sync);
1716
+ queueMicrotask(sync);
1717
+ }
1718
+ }
1719
+ function nativeFormProperty(el2, name) {
1720
+ const attribute = name.toLowerCase();
1721
+ if (attribute !== "value" && attribute !== "checked" && attribute !== "selected") return;
1722
+ if (el2.namespaceURI !== "http://www.w3.org/1999/xhtml") return;
1723
+ const tag = el2.localName;
1724
+ if (attribute === "value" && (tag === "input" || tag === "textarea" || tag === "select")) return attribute;
1725
+ if (attribute === "checked" && tag === "input") return attribute;
1726
+ if (attribute === "selected" && tag === "option") return attribute;
1727
+ }
1728
+ function syncFormProperty(el2, property, value) {
1729
+ if (property === "value") {
1730
+ const control = el2;
1731
+ const next = value == null || typeof value === "boolean" ? "" : String(value);
1732
+ if (el2.localName === "input" && el2.type === "file" && next !== "") return;
1733
+ if (el2.localName === "select" || control.value !== next) control.value = next;
1734
+ } else {
1735
+ const control = el2;
1736
+ const next = value != null && value !== false;
1737
+ if (control[property] !== next) control[property] = next;
1689
1738
  }
1690
1739
  }
1691
1740
  function bindClassAttribute(el2, value, bindings, disposers) {
@@ -1941,11 +1990,28 @@ function each(items, keyFn, templateFn) {
1941
1990
  entry.wrapper.parentNode?.removeChild(entry.wrapper);
1942
1991
  }
1943
1992
  }
1944
- let cursor = startMarker;
1945
- for (const entry of newEntries) {
1993
+ const atomic = canMoveWithin(parent);
1994
+ let focusedIndex = -1;
1995
+ if (!atomic) {
1996
+ const root = parent.getRootNode();
1997
+ let active = "activeElement" in root ? root.activeElement : null;
1998
+ while (active && active.parentNode !== parent) active = active.parentElement;
1999
+ if (active) focusedIndex = newEntries.findIndex((entry) => entry.wrapper === active);
2000
+ }
2001
+ if (focusedIndex !== -1) {
2002
+ let next = newEntries[focusedIndex].wrapper;
2003
+ for (let i = focusedIndex - 1; i >= 0; i--) {
2004
+ const wrapper = newEntries[i].wrapper;
2005
+ if (wrapper.nextSibling !== next) parent.insertBefore(wrapper, next);
2006
+ next = wrapper;
2007
+ }
2008
+ }
2009
+ let cursor = focusedIndex === -1 ? startMarker : newEntries[focusedIndex].wrapper;
2010
+ for (let i = focusedIndex + 1; i < newEntries.length; i++) {
2011
+ const entry = newEntries[i];
1946
2012
  const nextSibling = cursor.nextSibling;
1947
2013
  if (nextSibling !== entry.wrapper) {
1948
- if (entry.wrapper.parentNode === parent && canMoveWithin(parent)) {
2014
+ if (entry.wrapper.parentNode === parent && atomic) {
1949
2015
  parent.moveBefore(entry.wrapper, nextSibling);
1950
2016
  } else {
1951
2017
  parent.insertBefore(entry.wrapper, nextSibling);
@@ -1985,8 +2051,11 @@ function el(tag, props = {}, children2) {
1985
2051
  mount(host) {
1986
2052
  const element = document.createElement(tag);
1987
2053
  node = element;
2054
+ let afterChildren;
2055
+ const afterMount = [];
1988
2056
  for (const [key, val] of Object.entries(props)) {
1989
- if (val === void 0) continue;
2057
+ const formProperty = nativeFormProperty(element, key);
2058
+ if (val === void 0 && !formProperty) continue;
1990
2059
  if (key === "ref") {
1991
2060
  if (isRef(val)) {
1992
2061
  val.current = element;
@@ -2006,7 +2075,11 @@ function el(tag, props = {}, children2) {
2006
2075
  bindClassAttribute(element, val, bindings, disposers);
2007
2076
  continue;
2008
2077
  }
2009
- bindPlainAttribute(element, key, val, bindings, disposers);
2078
+ if (formProperty) {
2079
+ (afterChildren ??= []).push(() => bindPlainAttribute(element, key, val, bindings, disposers, afterMount));
2080
+ } else {
2081
+ bindPlainAttribute(element, key, val, bindings, disposers, afterMount);
2082
+ }
2010
2083
  }
2011
2084
  const flat = [];
2012
2085
  flattenChildren(children2, flat);
@@ -2015,7 +2088,9 @@ function el(tag, props = {}, children2) {
2015
2088
  element.appendChild(anchor);
2016
2089
  replaceMarkerWithBinding(anchor, child, bindings, disposers);
2017
2090
  }
2091
+ if (afterChildren) for (const bind of afterChildren) bind();
2018
2092
  host.appendChild(element);
2093
+ for (const sync of afterMount) sync();
2019
2094
  },
2020
2095
  dispose() {
2021
2096
  for (const d of disposers) {