@oscarpalmer/abydon 0.22.0 → 0.23.0
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/abydon.full.mjs +222 -160
- package/dist/attribute/index.d.mts +3 -2
- package/dist/attribute/index.mjs +21 -16
- package/dist/attribute/value.mjs +18 -28
- package/dist/constants.d.mts +4 -8
- package/dist/constants.mjs +6 -10
- package/dist/fragment.d.mts +27 -14
- package/dist/fragment.mjs +32 -16
- package/dist/fragments.d.mts +1 -2
- package/dist/fragments.mjs +2 -2
- package/dist/helpers/dom.d.mts +2 -3
- package/dist/helpers/dom.mjs +2 -4
- package/dist/helpers/index.d.mts +9 -5
- package/dist/helpers/index.mjs +11 -5
- package/dist/index.d.mts +33 -6
- package/dist/index.mjs +33 -6
- package/dist/models.d.mts +6 -4
- package/dist/node/index.mjs +18 -33
- package/dist/node/value.mjs +67 -50
- package/package.json +2 -2
- package/src/attribute/index.ts +41 -35
- package/src/attribute/value.ts +20 -53
- package/src/constants.ts +6 -14
- package/src/fragment.ts +34 -17
- package/src/fragments.ts +4 -2
- package/src/helpers/dom.ts +3 -5
- package/src/helpers/index.ts +19 -5
- package/src/index.ts +33 -6
- package/src/models.ts +6 -4
- package/src/node/index.ts +25 -63
- package/src/node/value.ts +117 -85
- package/src/parse.ts +1 -1
package/dist/abydon.full.mjs
CHANGED
|
@@ -783,6 +783,14 @@ function isEventTarget(value) {
|
|
|
783
783
|
function isHTMLOrSVGElement(value) {
|
|
784
784
|
return value instanceof HTMLElement || value instanceof SVGElement;
|
|
785
785
|
}
|
|
786
|
+
/**
|
|
787
|
+
* Is the value an input element? _(`<input>`, `<select>`, or `<textarea>`)_
|
|
788
|
+
* @param value Value to check
|
|
789
|
+
* @returns `true` if it's an input element, otherwise `false`
|
|
790
|
+
*/
|
|
791
|
+
function isInputElement(value) {
|
|
792
|
+
return value instanceof HTMLInputElement || value instanceof HTMLSelectElement || value instanceof HTMLTextAreaElement;
|
|
793
|
+
}
|
|
786
794
|
//#endregion
|
|
787
795
|
//#region node_modules/@oscarpalmer/toretto/dist/is.mjs
|
|
788
796
|
/**
|
|
@@ -1062,6 +1070,10 @@ const delimiters = {
|
|
|
1062
1070
|
let memoizedCapitalize;
|
|
1063
1071
|
//#endregion
|
|
1064
1072
|
//#region node_modules/@oscarpalmer/toretto/dist/internal/element-value.mjs
|
|
1073
|
+
function ignoreSetAttribute(element, name) {
|
|
1074
|
+
if (element instanceof HTMLTextAreaElement && name === "value") return true;
|
|
1075
|
+
return false;
|
|
1076
|
+
}
|
|
1065
1077
|
function normalizeKey(key, style) {
|
|
1066
1078
|
return style && key.startsWith(CSS_VARIABLE_PREFIX) ? key : kebabCase(key);
|
|
1067
1079
|
}
|
|
@@ -1091,16 +1103,21 @@ function setElementValues(element, first, second, third, callback, style) {
|
|
|
1091
1103
|
}
|
|
1092
1104
|
function updateElementValue(element, key, value, set, remove, isBoolean, json) {
|
|
1093
1105
|
if (isBoolean ? value == null : isNullableOrWhitespace(value)) remove.call(element, key);
|
|
1094
|
-
else set.call(element, key, json ? JSON.stringify(value) :
|
|
1106
|
+
else if (!ignoreSetAttribute(element, key)) set.call(element, key, json ? JSON.stringify(value) : getString(value));
|
|
1095
1107
|
}
|
|
1096
1108
|
const CSS_VARIABLE_PREFIX = "--";
|
|
1097
1109
|
//#endregion
|
|
1098
1110
|
//#region node_modules/@oscarpalmer/toretto/dist/internal/property.mjs
|
|
1111
|
+
function getPropertyValue(element, name, value) {
|
|
1112
|
+
if (isInputElement(element) && name === "value") return getString(value);
|
|
1113
|
+
return value;
|
|
1114
|
+
}
|
|
1099
1115
|
function updateProperty(element, name, value, dispatch) {
|
|
1100
1116
|
let property = name;
|
|
1101
1117
|
if (!(property in element)) property = camelCase(name);
|
|
1102
|
-
|
|
1103
|
-
element[property]
|
|
1118
|
+
const next = getPropertyValue(element, name, value);
|
|
1119
|
+
if (!(property in element) || Object.is(element[property], next)) return;
|
|
1120
|
+
element[property] = next;
|
|
1104
1121
|
const event = dispatch && elementEvents[element.tagName]?.[property];
|
|
1105
1122
|
if (typeof event === "string") element.dispatchEvent(new Event(event, {
|
|
1106
1123
|
bubbles: true,
|
|
@@ -1141,7 +1158,7 @@ function handleAttribute(callback, decode, first, second) {
|
|
|
1141
1158
|
let value;
|
|
1142
1159
|
if (isAttribute(first)) {
|
|
1143
1160
|
name = first.name;
|
|
1144
|
-
value =
|
|
1161
|
+
value = getString(first.value);
|
|
1145
1162
|
} else if (typeof first === "string" && typeof second === "string") {
|
|
1146
1163
|
name = first;
|
|
1147
1164
|
value = second;
|
|
@@ -1413,7 +1430,7 @@ const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
|
|
|
1413
1430
|
const ARRAY_COMPARISON_REMOVED = "removed";
|
|
1414
1431
|
const CHANGE_INPUTS = new Set(["checkbox", "radio"]);
|
|
1415
1432
|
const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
|
|
1416
|
-
const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '
|
|
1433
|
+
const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<>'";
|
|
1417
1434
|
const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
|
|
1418
1435
|
const EVENT_CHANGE = "change";
|
|
1419
1436
|
const EVENT_INPUT = "input";
|
|
@@ -1432,12 +1449,12 @@ const EXPRESSION_ABYDON_CONTENT = /^abydon\.(\d+)$/;
|
|
|
1432
1449
|
const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
|
|
1433
1450
|
const EXPRESSION_ATTRIBUTE_STYLE_FULL = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
|
|
1434
1451
|
const EXPRESSION_ATTRIBUTE_STYLE_PREFIX = /^style\./;
|
|
1435
|
-
const
|
|
1452
|
+
const EXPRESSION_ATTRIBUTE_STYLE_VARIABLE = /^style\.--/;
|
|
1436
1453
|
const EXPRESSION_EVENT_ATTRIBUTE = /^@([\w-]+)(?::([a-z:]+))?="$/i;
|
|
1437
1454
|
const EXPRESSION_EVENT_NAME = /^@?([\w-]+)(?::([a-z:]+))?$/i;
|
|
1438
|
-
const EXPRESSION_EVENT_OPTIONS_ACTIVE = /^a(ctive)$/i;
|
|
1439
|
-
const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(apture)$/i;
|
|
1440
|
-
const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(nce)$/i;
|
|
1455
|
+
const EXPRESSION_EVENT_OPTIONS_ACTIVE = /^a(?:ctive)$/i;
|
|
1456
|
+
const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(?:apture)$/i;
|
|
1457
|
+
const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(?:nce)$/i;
|
|
1441
1458
|
const EXPRESSION_EVENT_PREFIX = /^@/;
|
|
1442
1459
|
const EXPRESSION_TEXTAREA_VALUE = /(?:<|<)!--abydon\.(\d+)--(?:>|>)/;
|
|
1443
1460
|
const NAME_FRAGMENT = "$fragment";
|
|
@@ -1453,17 +1470,17 @@ function compareArrays(first, second) {
|
|
|
1453
1470
|
return firstIsLarger ? ARRAY_COMPARISON_REMOVED : ARRAY_COMPARISON_ADDED;
|
|
1454
1471
|
}
|
|
1455
1472
|
/**
|
|
1456
|
-
* Is the value a
|
|
1473
|
+
* Is the value a _Fragment_?
|
|
1457
1474
|
* @param value Value to check
|
|
1458
|
-
* @returns `true` if the value is a
|
|
1475
|
+
* @returns `true` if the value is a _Fragment_, otherwise `false`
|
|
1459
1476
|
*/
|
|
1460
1477
|
function isFragment(value) {
|
|
1461
1478
|
return isNamed(value, NAME_FRAGMENT);
|
|
1462
1479
|
}
|
|
1463
1480
|
/**
|
|
1464
|
-
* Is the value a
|
|
1481
|
+
* Is the value a _Fragments_ instance?
|
|
1465
1482
|
* @param value Value to check
|
|
1466
|
-
* @returns `true` if the value is a
|
|
1483
|
+
* @returns `true` if the value is a _Fragments_ instance, otherwise `false`
|
|
1467
1484
|
*/
|
|
1468
1485
|
function isFragments(value) {
|
|
1469
1486
|
return isNamed(value, NAME_FRAGMENTS);
|
|
@@ -1471,6 +1488,11 @@ function isFragments(value) {
|
|
|
1471
1488
|
function isNamed(value, name) {
|
|
1472
1489
|
return typeof value === "object" && value != null && name in value && value[name] === true;
|
|
1473
1490
|
}
|
|
1491
|
+
function setComputedValue(data, callback, after) {
|
|
1492
|
+
const computation = computed(callback);
|
|
1493
|
+
data.mora.values.add(computation);
|
|
1494
|
+
after(computation);
|
|
1495
|
+
}
|
|
1474
1496
|
//#endregion
|
|
1475
1497
|
//#region src/fragments.ts
|
|
1476
1498
|
var Fragments = class {
|
|
@@ -1491,7 +1513,7 @@ var Fragments = class {
|
|
|
1491
1513
|
};
|
|
1492
1514
|
function handleFragments(item, remove) {
|
|
1493
1515
|
const state = isFragments(item) ? fragmentsStates.get(item) : item;
|
|
1494
|
-
(remove ? removeFragments
|
|
1516
|
+
(remove ? removeFragments : initializeFragments)(state);
|
|
1495
1517
|
}
|
|
1496
1518
|
function handleItems(state, items) {
|
|
1497
1519
|
const keys = /* @__PURE__ */ new Set();
|
|
@@ -1508,7 +1530,7 @@ function handleItems(state, items) {
|
|
|
1508
1530
|
instance = state.fragment(item);
|
|
1509
1531
|
if (!isFragment(instance)) throw new Error(ERROR_FRAGMENT);
|
|
1510
1532
|
}
|
|
1511
|
-
instance.
|
|
1533
|
+
instance.configure({ identifier: key });
|
|
1512
1534
|
state.instances[key] = instance;
|
|
1513
1535
|
keys.add(key);
|
|
1514
1536
|
mapped.push(instance);
|
|
@@ -1521,7 +1543,7 @@ function initializeFragments(state) {
|
|
|
1521
1543
|
handleItems(state, items);
|
|
1522
1544
|
});
|
|
1523
1545
|
}
|
|
1524
|
-
function removeFragments
|
|
1546
|
+
function removeFragments(state) {
|
|
1525
1547
|
state.subscriber?.();
|
|
1526
1548
|
updateFragments(state);
|
|
1527
1549
|
state.subscriber = void 0;
|
|
@@ -1547,9 +1569,6 @@ function createNodes(value) {
|
|
|
1547
1569
|
if (isChildNode(value)) return [value];
|
|
1548
1570
|
return [new Text(getString(value))];
|
|
1549
1571
|
}
|
|
1550
|
-
function isInputElement(node) {
|
|
1551
|
-
return node instanceof HTMLInputElement || node instanceof HTMLSelectElement;
|
|
1552
|
-
}
|
|
1553
1572
|
function removeNodes(nodes) {
|
|
1554
1573
|
const { length } = nodes;
|
|
1555
1574
|
for (let index = 0; index < length; index += 1) nodes[index].remove();
|
|
@@ -1558,6 +1577,7 @@ function replaceNodes(from, to) {
|
|
|
1558
1577
|
from[0]?.replaceWith(...to);
|
|
1559
1578
|
const { length } = from;
|
|
1560
1579
|
for (let index = 1; index < length; index += 1) from[index].remove();
|
|
1580
|
+
return to;
|
|
1561
1581
|
}
|
|
1562
1582
|
//#endregion
|
|
1563
1583
|
//#region node_modules/@oscarpalmer/toretto/dist/internal/get-value.mjs
|
|
@@ -1721,8 +1741,8 @@ function setStyle(element, property, value) {
|
|
|
1721
1741
|
}
|
|
1722
1742
|
function updateStyleProperty(element, key, value) {
|
|
1723
1743
|
updateElementValue(element, key, value, function(property, style) {
|
|
1724
|
-
if (property.startsWith(VARIABLE_PREFIX)) this.style.setProperty(property,
|
|
1725
|
-
else this.style[property] =
|
|
1744
|
+
if (property.startsWith(VARIABLE_PREFIX)) this.style.setProperty(property, getString(style));
|
|
1745
|
+
else this.style[property] = getString(style);
|
|
1726
1746
|
}, function(property) {
|
|
1727
1747
|
if (property.startsWith(VARIABLE_PREFIX)) this.style.removeProperty(property);
|
|
1728
1748
|
else this.style[property] = "";
|
|
@@ -1733,12 +1753,12 @@ const ATTRIBUTE_STYLE = "style";
|
|
|
1733
1753
|
const VARIABLE_PREFIX = "--";
|
|
1734
1754
|
//#endregion
|
|
1735
1755
|
//#region src/attribute/value.ts
|
|
1736
|
-
function getStyleValue(value, unit,
|
|
1737
|
-
if (removeStyleValue(value, unit,
|
|
1756
|
+
function getStyleValue(value, unit, isVariable) {
|
|
1757
|
+
if (removeStyleValue(value, unit, isVariable)) return;
|
|
1738
1758
|
return value === true || value === "true" ? unit : `${getString(value)}${unit ?? ""}`;
|
|
1739
1759
|
}
|
|
1740
|
-
function removeStyleValue(value, unit,
|
|
1741
|
-
if (value == null || value === false ||
|
|
1760
|
+
function removeStyleValue(value, unit, isVariable) {
|
|
1761
|
+
if (value == null || value === false || isVariable && isNullableOrWhitespace(value)) return true;
|
|
1742
1762
|
return unit == null && (value === true || value === "true");
|
|
1743
1763
|
}
|
|
1744
1764
|
function setAttribute(data, element, name, value) {
|
|
@@ -1755,78 +1775,73 @@ function setAttribute(data, element, name, value) {
|
|
|
1755
1775
|
}
|
|
1756
1776
|
}
|
|
1757
1777
|
function setClassValues(data, element, name, value) {
|
|
1758
|
-
|
|
1778
|
+
const classes = name.slice(6).split(".");
|
|
1779
|
+
updateValue(data, value, (value) => {
|
|
1759
1780
|
if (value === true || value === "true") element.classList.add(...classes);
|
|
1760
1781
|
else element.classList.remove(...classes);
|
|
1761
|
-
}
|
|
1762
|
-
const classes = name.slice(6).split(".");
|
|
1763
|
-
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
|
|
1764
|
-
else update(value);
|
|
1782
|
+
});
|
|
1765
1783
|
}
|
|
1766
1784
|
function setStyleValues(data, element, name, value) {
|
|
1767
1785
|
let [, property, unit] = EXPRESSION_ATTRIBUTE_STYLE_FULL.exec(name);
|
|
1768
|
-
const
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
setStyle(element, property, getStyleValue(value, unit, isProperty));
|
|
1773
|
-
}
|
|
1774
|
-
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
|
|
1775
|
-
else update(value);
|
|
1786
|
+
const isVariable = EXPRESSION_ATTRIBUTE_STYLE_VARIABLE.test(name);
|
|
1787
|
+
updateValue(data, value, (value) => {
|
|
1788
|
+
setStyle(element, property, getStyleValue(value, unit, isVariable));
|
|
1789
|
+
});
|
|
1776
1790
|
}
|
|
1777
1791
|
function setValue(data, element, name, value) {
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
setAttribute$1(element, name, next);
|
|
1782
|
-
}));
|
|
1783
|
-
else setAttribute$1(element, name, value);
|
|
1792
|
+
updateValue(data, value, (value) => {
|
|
1793
|
+
setAttribute$1(element, name, value);
|
|
1794
|
+
});
|
|
1784
1795
|
}
|
|
1785
|
-
function
|
|
1786
|
-
if (
|
|
1787
|
-
|
|
1796
|
+
function updateValue(data, value, updater) {
|
|
1797
|
+
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(updater));
|
|
1798
|
+
else updater(value);
|
|
1788
1799
|
}
|
|
1789
1800
|
//#endregion
|
|
1790
1801
|
//#region src/attribute/index.ts
|
|
1802
|
+
function compareAttributes(first, second) {
|
|
1803
|
+
return first.name.localeCompare(second.name);
|
|
1804
|
+
}
|
|
1791
1805
|
function getValue(data, original) {
|
|
1792
1806
|
const matches = EXPRESSION_ABYDON_CONTENT.exec(original);
|
|
1793
1807
|
return matches == null ? original : data.values[+matches[1]];
|
|
1794
1808
|
}
|
|
1795
|
-
function
|
|
1796
|
-
|
|
1809
|
+
function mapAttributeValue(data, element, name, value) {
|
|
1810
|
+
if (typeof value === "function") setComputedAttribute(data, element, name, value);
|
|
1811
|
+
else setAttribute(data, element, name, value);
|
|
1812
|
+
if (isInputElement(element) && isSignal(value) && name in element) mapEvent(element, "on", () => {
|
|
1813
|
+
value.set(element[name]);
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
function mapAttributes(data, element, ignoreValue) {
|
|
1817
|
+
const attributes = [...element.attributes].sort(compareAttributes);
|
|
1797
1818
|
const { length } = attributes;
|
|
1798
1819
|
for (let index = 0; index < length; index += 1) {
|
|
1799
1820
|
const { name, value } = attributes[index];
|
|
1800
1821
|
const actualName = name.replace(EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, "");
|
|
1801
1822
|
const actualValue = getValue(data, value);
|
|
1802
1823
|
if (actualName !== name) element.removeAttribute(name);
|
|
1824
|
+
if (actualName === "value" && ignoreValue) continue;
|
|
1803
1825
|
switch (true) {
|
|
1804
1826
|
case EXPRESSION_EVENT_PREFIX.test(actualName):
|
|
1805
1827
|
mapEvent(element, actualName, actualValue);
|
|
1806
1828
|
break;
|
|
1807
1829
|
default:
|
|
1808
|
-
|
|
1830
|
+
mapAttributeValue(data, element, actualName, actualValue);
|
|
1809
1831
|
break;
|
|
1810
1832
|
}
|
|
1811
1833
|
}
|
|
1812
1834
|
}
|
|
1813
|
-
function mapValue$1(data, element, name, value) {
|
|
1814
|
-
if (typeof value === "function") setComputedAttribute(data, element, name, value);
|
|
1815
|
-
else setAttribute(data, element, name, value);
|
|
1816
|
-
if (isInputElement(element) && isSignal(value) && name in element) mapEvent(element, "on", () => {
|
|
1817
|
-
value.set(element[name]);
|
|
1818
|
-
});
|
|
1819
|
-
}
|
|
1820
1835
|
function setComputedAttribute(data, element, name, callback) {
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1836
|
+
setComputedValue(data, callback, (computation) => {
|
|
1837
|
+
setAttribute(data, element, name, computation);
|
|
1838
|
+
});
|
|
1824
1839
|
}
|
|
1825
1840
|
//#endregion
|
|
1826
1841
|
//#region src/node/value.ts
|
|
1827
1842
|
function addToArray(identifiers, items, nodes, added) {
|
|
1828
1843
|
let position = nodes[0];
|
|
1829
|
-
const before = added && !identifiers.previous.has(items.templates[0].identifier);
|
|
1844
|
+
const before = added && !identifiers.previous.set.has(items.templates[0].identifier);
|
|
1830
1845
|
const next = items.next.flatMap((fragment) => fragment.get().flatMap((node) => ({
|
|
1831
1846
|
identifier: fragment.identifier,
|
|
1832
1847
|
value: node
|
|
@@ -1834,19 +1849,48 @@ function addToArray(identifiers, items, nodes, added) {
|
|
|
1834
1849
|
const { length } = next;
|
|
1835
1850
|
for (let index = 0; index < length; index += 1) {
|
|
1836
1851
|
const node = next[index];
|
|
1837
|
-
if (!(added && identifiers.previous.has(node.identifier))) if (index === 0 && before) position.before(node.value);
|
|
1852
|
+
if (!(added && identifiers.previous.set.has(node.identifier))) if (index === 0 && before) position.before(node.value);
|
|
1838
1853
|
else position.after(node.value);
|
|
1839
1854
|
position = node.value;
|
|
1840
1855
|
}
|
|
1841
1856
|
}
|
|
1857
|
+
function getArrayData(item, values) {
|
|
1858
|
+
const { length } = values;
|
|
1859
|
+
const next = [];
|
|
1860
|
+
let templates = [];
|
|
1861
|
+
for (let index = 0; index < length; index += 1) {
|
|
1862
|
+
const value = values[index];
|
|
1863
|
+
if (isFragment(value) && value.identifier != null) {
|
|
1864
|
+
next.push(value.identifier);
|
|
1865
|
+
templates.push(value);
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
const previous = item.fragments?.map((fragment) => fragment.identifier) ?? [];
|
|
1869
|
+
const nextSet = new Set(next);
|
|
1870
|
+
if (nextSet.size !== templates.length) templates = [];
|
|
1871
|
+
return {
|
|
1872
|
+
next: {
|
|
1873
|
+
array: next,
|
|
1874
|
+
set: nextSet
|
|
1875
|
+
},
|
|
1876
|
+
previous: {
|
|
1877
|
+
array: previous,
|
|
1878
|
+
set: new Set(previous)
|
|
1879
|
+
},
|
|
1880
|
+
template: {
|
|
1881
|
+
empty: templates.length === 0,
|
|
1882
|
+
items: templates
|
|
1883
|
+
}
|
|
1884
|
+
};
|
|
1885
|
+
}
|
|
1842
1886
|
function handleArray(identifiers, items, nodes) {
|
|
1843
|
-
const next = items.templates.map((template) => items.fragments
|
|
1844
|
-
const comparison = compareArrays(
|
|
1887
|
+
const next = items.templates.map((template) => items.fragments.find((fragment) => fragment.identifier === template.identifier) ?? template);
|
|
1888
|
+
const comparison = compareArrays(identifiers.previous.array, identifiers.next.array);
|
|
1845
1889
|
if (comparison !== "removed") addToArray(identifiers, {
|
|
1846
1890
|
...items,
|
|
1847
1891
|
next
|
|
1848
1892
|
}, nodes, comparison === ARRAY_COMPARISON_ADDED);
|
|
1849
|
-
const toRemove = items.fragments
|
|
1893
|
+
const toRemove = items.fragments.filter((fragment) => !identifiers.next.set.has(fragment.identifier));
|
|
1850
1894
|
const { length } = toRemove;
|
|
1851
1895
|
for (let index = 0; index < length; index += 1) toRemove[index].remove();
|
|
1852
1896
|
return {
|
|
@@ -1854,52 +1898,45 @@ function handleArray(identifiers, items, nodes) {
|
|
|
1854
1898
|
nodes: next.flatMap((fragment) => fragment.get())
|
|
1855
1899
|
};
|
|
1856
1900
|
}
|
|
1857
|
-
function
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1901
|
+
function removeArray(item, comment) {
|
|
1902
|
+
const fragments = (item.fragments ?? []).slice();
|
|
1903
|
+
const result = { nodes: setText(item, comment) };
|
|
1904
|
+
removeFragmentsItems(fragments);
|
|
1905
|
+
return result;
|
|
1862
1906
|
}
|
|
1863
|
-
function
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
else to = item.text == null ? [] : [item.text];
|
|
1867
|
-
replaceNodes(item.nodes ?? [], to);
|
|
1907
|
+
function removeFragmentsItems(fragments) {
|
|
1908
|
+
const { length } = fragments;
|
|
1909
|
+
for (let index = 0; index < length; index += 1) fragments[index].remove();
|
|
1868
1910
|
}
|
|
1869
1911
|
function setArray(item, comment, value) {
|
|
1870
|
-
if (value.length === 0) return
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
fragments
|
|
1879
|
-
|
|
1880
|
-
}
|
|
1912
|
+
if (value.length === 0) return removeArray(item, comment);
|
|
1913
|
+
const { next, previous, template } = getArrayData(item, value);
|
|
1914
|
+
if (template.empty || item.nodes == null || previous.array.some((identifier) => identifier == null)) {
|
|
1915
|
+
const fragments = (item.fragments ?? []).slice();
|
|
1916
|
+
const result = {
|
|
1917
|
+
fragments: template.empty ? void 0 : template.items,
|
|
1918
|
+
nodes: replaceNodes(item.nodes ?? [comment], template.empty ? value.flatMap((item) => createNodes(item)) : template.items.flatMap((template) => template.get()))
|
|
1919
|
+
};
|
|
1920
|
+
removeFragmentsItems(fragments);
|
|
1921
|
+
return result;
|
|
1922
|
+
}
|
|
1881
1923
|
return handleArray({
|
|
1882
|
-
next
|
|
1883
|
-
previous
|
|
1924
|
+
next,
|
|
1925
|
+
previous
|
|
1884
1926
|
}, {
|
|
1885
|
-
|
|
1886
|
-
|
|
1927
|
+
fragments: item.fragments ?? [],
|
|
1928
|
+
templates: template.items
|
|
1887
1929
|
}, item.nodes);
|
|
1888
1930
|
}
|
|
1889
1931
|
function setNodes(item, comment, next) {
|
|
1890
|
-
|
|
1891
|
-
else replaceNodes(item.nodes, next);
|
|
1892
|
-
removeFragments(item.fragments);
|
|
1893
|
-
return next;
|
|
1932
|
+
return replaceNodes(item.nodes ?? [comment], next);
|
|
1894
1933
|
}
|
|
1895
1934
|
function setReactiveValue(data, comment, reactive) {
|
|
1896
1935
|
let item = data.items.find((item) => item.nodes?.includes(comment));
|
|
1897
1936
|
item ??= {};
|
|
1898
|
-
item.text = new Text();
|
|
1899
1937
|
data.mora.subscribers.add(reactive.subscribe((value) => {
|
|
1900
1938
|
if (Array.isArray(value)) setReactiveValueForArray(item, comment, value);
|
|
1901
1939
|
else setReactiveValueForSingle(item, comment, value);
|
|
1902
|
-
item.nodes ??= [comment];
|
|
1903
1940
|
}));
|
|
1904
1941
|
}
|
|
1905
1942
|
function setReactiveValueForArray(item, comment, value) {
|
|
@@ -1908,25 +1945,20 @@ function setReactiveValueForArray(item, comment, value) {
|
|
|
1908
1945
|
item.nodes = nodes;
|
|
1909
1946
|
}
|
|
1910
1947
|
function setReactiveValueForSingle(item, comment, value) {
|
|
1948
|
+
const fragments = (item.fragments ?? []).slice();
|
|
1911
1949
|
const valueIsFragment = isFragment(value);
|
|
1912
|
-
item.fragments = valueIsFragment ? [value] : void 0;
|
|
1913
1950
|
if (valueIsFragment || isChildNode(value)) item.nodes = setNodes(item, comment, createNodes(value));
|
|
1914
1951
|
else item.nodes = setText(item, comment, value);
|
|
1952
|
+
item.fragments = valueIsFragment ? [value] : void 0;
|
|
1953
|
+
removeFragmentsItems(fragments);
|
|
1915
1954
|
}
|
|
1916
1955
|
function setText(item, comment, value) {
|
|
1917
|
-
const
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
} else if (isNullable && comment.parentNode == null) item.text?.replaceWith(comment);
|
|
1924
|
-
else if (!isNullable && item?.text?.parentNode == null) {
|
|
1925
|
-
if (item.text != null) comment.replaceWith(item.text);
|
|
1926
|
-
result = true;
|
|
1927
|
-
}
|
|
1928
|
-
removeFragments(item.fragments);
|
|
1929
|
-
if (result) return item.text == null ? [] : [item.text];
|
|
1956
|
+
const valueIsNullable = isNullableOrWhitespace(value);
|
|
1957
|
+
item.text ??= new Text();
|
|
1958
|
+
item.text.textContent = valueIsNullable ? "" : getString(value);
|
|
1959
|
+
const result = valueIsNullable ? [comment] : [item.text];
|
|
1960
|
+
replaceNodes(item.nodes ?? [comment], result);
|
|
1961
|
+
return result;
|
|
1930
1962
|
}
|
|
1931
1963
|
//#endregion
|
|
1932
1964
|
//#region src/node/index.ts
|
|
@@ -1943,42 +1975,29 @@ function mapNodes(data, nodes) {
|
|
|
1943
1975
|
mapNode(data, node);
|
|
1944
1976
|
continue;
|
|
1945
1977
|
}
|
|
1946
|
-
if (node
|
|
1947
|
-
|
|
1978
|
+
if (isHTMLOrSVGElement(node)) {
|
|
1979
|
+
let ignoreValueAttribute = false;
|
|
1980
|
+
if (node instanceof HTMLTextAreaElement) ignoreValueAttribute = mapTextarea(data, node);
|
|
1981
|
+
mapAttributes(data, node, ignoreValueAttribute);
|
|
1982
|
+
}
|
|
1948
1983
|
if (node.hasChildNodes()) mapNodes(data, [...node.childNodes]);
|
|
1949
1984
|
}
|
|
1950
1985
|
}
|
|
1951
1986
|
function mapTextarea(data, element) {
|
|
1952
1987
|
const [, index] = EXPRESSION_TEXTAREA_VALUE.exec(element.textContent) ?? EXPRESSION_TEXTAREA_VALUE.exec(element.value) ?? [];
|
|
1953
|
-
if (index == null) return;
|
|
1988
|
+
if (index == null) return false;
|
|
1954
1989
|
element.textContent = "";
|
|
1955
1990
|
element.value = "";
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
element.value = getString(value.peek());
|
|
1959
|
-
mapEvent(element, "on", () => {
|
|
1960
|
-
value.set(element.value);
|
|
1961
|
-
});
|
|
1962
|
-
data.mora.subscribers.add(value.subscribe((value) => {
|
|
1963
|
-
element.value = getString(value);
|
|
1964
|
-
}));
|
|
1965
|
-
return;
|
|
1966
|
-
}
|
|
1967
|
-
let reactive;
|
|
1968
|
-
if (typeof value === "function") reactive = computed(value);
|
|
1969
|
-
else if (isComputed(value)) reactive = value;
|
|
1970
|
-
if (reactive == null) element.value = "";
|
|
1971
|
-
else data.mora.subscribers.add(reactive.subscribe((value) => {
|
|
1972
|
-
element.value = getString(value);
|
|
1973
|
-
}));
|
|
1991
|
+
mapAttributeValue(data, element, "value", data.values[Number.parseInt(index, 10)]);
|
|
1992
|
+
return true;
|
|
1974
1993
|
}
|
|
1975
1994
|
function mapValue(data, comment, value) {
|
|
1976
1995
|
switch (true) {
|
|
1977
1996
|
case typeof value === "function":
|
|
1978
|
-
|
|
1997
|
+
setComputedNode(data, comment, value);
|
|
1979
1998
|
break;
|
|
1980
1999
|
case isFragments(value):
|
|
1981
|
-
|
|
2000
|
+
setFragmentsNode(data, comment, value);
|
|
1982
2001
|
break;
|
|
1983
2002
|
case isReactive(value):
|
|
1984
2003
|
setReactiveValue(data, comment, value);
|
|
@@ -1997,12 +2016,12 @@ function replaceComment(data, comment, value) {
|
|
|
1997
2016
|
}
|
|
1998
2017
|
comment.replaceWith(...nodes);
|
|
1999
2018
|
}
|
|
2000
|
-
function
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2019
|
+
function setComputedNode(data, comment, callback) {
|
|
2020
|
+
setComputedValue(data, callback, (computation) => {
|
|
2021
|
+
setReactiveValue(data, comment, computation);
|
|
2022
|
+
});
|
|
2004
2023
|
}
|
|
2005
|
-
function
|
|
2024
|
+
function setFragmentsNode(data, comment, fragments) {
|
|
2006
2025
|
const state = fragmentsStates.get(fragments);
|
|
2007
2026
|
handleFragments(state, false);
|
|
2008
2027
|
setReactiveValue(data, comment, state.mapped);
|
|
@@ -2048,11 +2067,13 @@ var Fragment = class {
|
|
|
2048
2067
|
/**
|
|
2049
2068
|
* Is template caching enabled?
|
|
2050
2069
|
*/
|
|
2051
|
-
get
|
|
2070
|
+
get cache() {
|
|
2052
2071
|
return this.#configuration.cache;
|
|
2053
2072
|
}
|
|
2054
2073
|
/**
|
|
2055
|
-
*
|
|
2074
|
+
* Identifier for the _Fragment_
|
|
2075
|
+
*
|
|
2076
|
+
* _An identifier can be used to uniquely identify a Fragment, which helps prevent re-rendering in reactive arrays and Fragments_
|
|
2056
2077
|
*/
|
|
2057
2078
|
get identifier() {
|
|
2058
2079
|
return this.#configuration.identifier;
|
|
@@ -2071,16 +2092,32 @@ var Fragment = class {
|
|
|
2071
2092
|
};
|
|
2072
2093
|
}
|
|
2073
2094
|
/**
|
|
2074
|
-
*
|
|
2095
|
+
* Insert the _Fragment_ after the given element
|
|
2096
|
+
* @param element Element to insert after
|
|
2097
|
+
*/
|
|
2098
|
+
after(element) {
|
|
2099
|
+
element.after(...this.get());
|
|
2100
|
+
}
|
|
2101
|
+
/**
|
|
2102
|
+
* Append the _Fragment_ to the given element
|
|
2075
2103
|
* @param element Element to append to
|
|
2076
2104
|
*/
|
|
2077
2105
|
appendTo(element) {
|
|
2078
2106
|
element.append(...this.get());
|
|
2079
2107
|
}
|
|
2080
2108
|
/**
|
|
2081
|
-
*
|
|
2109
|
+
* Insert the _Fragment_ before the given element
|
|
2110
|
+
* @param element Element to insert before
|
|
2111
|
+
*/
|
|
2112
|
+
before(element) {
|
|
2113
|
+
element.before(...this.get());
|
|
2114
|
+
}
|
|
2115
|
+
/**
|
|
2116
|
+
* Configure the _Fragment_
|
|
2117
|
+
*
|
|
2118
|
+
* _Returns the Fragment instance for chaining_
|
|
2082
2119
|
* @param configuration Configuration options
|
|
2083
|
-
* @returns
|
|
2120
|
+
* @returns _Fragment_
|
|
2084
2121
|
*/
|
|
2085
2122
|
configure(configuration) {
|
|
2086
2123
|
const actual = isPlainObject(configuration) ? configuration : {};
|
|
@@ -2089,7 +2126,7 @@ var Fragment = class {
|
|
|
2089
2126
|
return this;
|
|
2090
2127
|
}
|
|
2091
2128
|
/**
|
|
2092
|
-
* Get a list of the
|
|
2129
|
+
* Get a list of the _Fragment_'s nodes
|
|
2093
2130
|
* @returns List of nodes
|
|
2094
2131
|
*/
|
|
2095
2132
|
get() {
|
|
@@ -2102,19 +2139,17 @@ var Fragment = class {
|
|
|
2102
2139
|
return data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes);
|
|
2103
2140
|
}
|
|
2104
2141
|
/**
|
|
2105
|
-
*
|
|
2106
|
-
*
|
|
2107
|
-
* _An identifier can be used to uniquely identify a fragment,
|
|
2108
|
-
* which helps prevent re-rendering in certain scenarios._
|
|
2109
|
-
* @param identifier Identifier
|
|
2110
|
-
* @returns Fragment
|
|
2142
|
+
* Prepend the _Fragment_ to the given element
|
|
2143
|
+
* @param element Element to prepend to
|
|
2111
2144
|
*/
|
|
2112
|
-
|
|
2113
|
-
this
|
|
2114
|
-
return this;
|
|
2145
|
+
prependTo(element) {
|
|
2146
|
+
element.prepend(...this.get());
|
|
2115
2147
|
}
|
|
2116
2148
|
/**
|
|
2117
|
-
* Remove the
|
|
2149
|
+
* Remove the _Fragment_ _(and all its descendants)_ from the _DOM_
|
|
2150
|
+
*
|
|
2151
|
+
* - _Any events, reactive values, and Fragments will also be cleaned up and removed_
|
|
2152
|
+
* - _After being removed, the Fragment can be re-inserted into the DOM_
|
|
2118
2153
|
*/
|
|
2119
2154
|
remove() {
|
|
2120
2155
|
removeFragment(this.#data);
|
|
@@ -2145,11 +2180,27 @@ function removeMora(data) {
|
|
|
2145
2180
|
//#endregion
|
|
2146
2181
|
//#region src/index.ts
|
|
2147
2182
|
/**
|
|
2148
|
-
* Create a
|
|
2183
|
+
* Create a _Fragments_ instance from a reactive array
|
|
2184
|
+
*
|
|
2185
|
+
* _A Fragments instance can be used to efficiently render a list of items that may change over time, using unique identifiers to track each item, only adding, removing, or updating each related Fragment._
|
|
2186
|
+
*
|
|
2187
|
+
* @example
|
|
2188
|
+
* ```ts
|
|
2189
|
+
* const fruits = array(['Apple', 'Banana', 'Cherry']);
|
|
2190
|
+
* const items = fragments(
|
|
2191
|
+
* fruits,
|
|
2192
|
+
* fruit => fruit, // Identifies a unique item
|
|
2193
|
+
* fruit => html`<p>${fruit}</p>`, // Creates a Fragment from an item
|
|
2194
|
+
* );
|
|
2195
|
+
* html`${items}`.appendTo(document.body) // Renders '<p>Apple</p><p>Banana</p><p>Cherry</p>'
|
|
2196
|
+
* fruits.push(['Date', 'Elderberry', 'Fig']); // Appends '<p>Date</p><p>Elderberry</p><p>Fig</p>'
|
|
2197
|
+
* // without re-rendering the existing Fragments
|
|
2198
|
+
* ```
|
|
2199
|
+
*
|
|
2149
2200
|
* @param array Reactive array
|
|
2150
|
-
* @param identify Function to identify item
|
|
2151
|
-
* @param fragment Function to create
|
|
2152
|
-
* @returns
|
|
2201
|
+
* @param identify Function to identify item uniquely _(non-nullable)_
|
|
2202
|
+
* @param fragment Function to create _Fragment_ from item
|
|
2203
|
+
* @returns _Fragments_
|
|
2153
2204
|
*/
|
|
2154
2205
|
function fragments(array, identify, fragment) {
|
|
2155
2206
|
if (!isArray(array)) throw new TypeError("Fragments array must be a reactive array");
|
|
@@ -2158,8 +2209,19 @@ function fragments(array, identify, fragment) {
|
|
|
2158
2209
|
return new Fragments(array, identify, fragment);
|
|
2159
2210
|
}
|
|
2160
2211
|
/**
|
|
2161
|
-
* Create a
|
|
2162
|
-
*
|
|
2212
|
+
* Create a _Fragment_ from a template
|
|
2213
|
+
*
|
|
2214
|
+
* _A Fragment can be used to efficiently render a template that may change over time, only updating the necessary parts of the DOM._
|
|
2215
|
+
*
|
|
2216
|
+
* @example
|
|
2217
|
+
* ```ts
|
|
2218
|
+
* const name = signal('World');
|
|
2219
|
+
* const fragment = html`<p>Hello, ${name}!</p>`;
|
|
2220
|
+
* fragment.appendTo(document.body); // Renders '<p>Hello, World!</p>'
|
|
2221
|
+
* name.set('Alice'); // Replaces 'World' with 'Alice'
|
|
2222
|
+
* ```
|
|
2223
|
+
*
|
|
2224
|
+
* @returns _Fragment_
|
|
2163
2225
|
*/
|
|
2164
2226
|
function html(template, ...values) {
|
|
2165
2227
|
return new Fragment(template, values);
|