@joist/element
Version:
Intelligently apply styles to WebComponents
89 lines • 2.96 kB
JavaScript
class Updates extends Set {
}
export function template({ tokenPrefix = "#:", value } = {}) {
let updates = null;
return function render(opts) {
if (!updates || opts?.refresh) {
updates = findUpdates(this, {
tokenPrefix,
value: value ?? ((key) => getTemplateValue(this, key)),
});
}
else {
for (const update of updates) {
update();
}
}
};
}
function findUpdates(el, opts) {
const iterator = document.createTreeWalker(el.shadowRoot ?? el, NodeFilter.SHOW_ELEMENT);
const updates = new Updates();
while (iterator.nextNode()) {
const res = trackElement(iterator.currentNode, updates, opts);
if (res !== null) {
iterator.currentNode = res;
}
}
return updates;
}
function trackElement(node, updates, opts) {
const element = node;
const getter = opts.value;
const tokenPrefix = opts.tokenPrefix;
for (const attr of element.attributes) {
const nodeValue = attr.value.trim();
const realAttributeName = attr.name.replace(tokenPrefix, "");
let update = null;
if (attr.name.startsWith(`${tokenPrefix}bind`)) {
update = () => {
const value = getter(attr.value);
if (element.textContent !== value) {
element.textContent = getter(attr.value);
}
};
}
else if (attr.name.startsWith(tokenPrefix)) {
const isBooleanAttr = nodeValue.startsWith("!");
const isPositive = nodeValue.startsWith("!!");
const propertyKey = nodeValue.replaceAll("!", "");
if (isBooleanAttr) {
update = () => {
const value = isPositive
? !!getter(propertyKey)
: !getter(propertyKey);
if (value) {
element.setAttribute(realAttributeName, "");
}
else {
element.removeAttribute(realAttributeName);
}
};
}
else {
const realAttribute = document.createAttribute(realAttributeName);
element.setAttributeNode(realAttribute);
update = () => {
const value = getter(nodeValue);
if (realAttribute.value !== value) {
realAttribute.value = value;
}
};
}
}
if (update) {
updates.add(update);
update();
}
}
return null;
}
export function getTemplateValue(obj, key) {
const parsed = key.split(".");
let pointer = obj;
for (const part of parsed) {
pointer = pointer[part];
}
return pointer;
}
//# sourceMappingURL=template.js.map