UNPKG

@joist/element

Version:

Intelligently apply styles to WebComponents

89 lines 2.96 kB
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