element-vir
Version:
Heroic. Reactive. Declarative. Type safe. Web components without compromise.
97 lines (96 loc) • 3.8 kB
JavaScript
import { check } from '@augment-vir/assert';
import { filterMap } from '@augment-vir/common';
import { hasTagName, isMinimalDefinitionWithInputs } from './minimal-element-definition.js';
function extractElementKeys(values) {
return filterMap(values, (value) => {
if (isMinimalDefinitionWithInputs(value)) {
return value.definition;
}
if (hasTagName(value)) {
return value.tagInterpolationKey || value;
}
return undefined;
}, check.isTruthy);
}
/**
* The transformed templates are written to a map so that we can preserve reference equality between
* calls. Without maintaining reference equality between html`` calls, lit-element reconstructs all
* of its children on every render.
*
* This is a WeakMap because we only care about the transformed array value as long as the original
* template array key exists.
*/
const transformedTemplateStrings = new WeakMap();
export function getAlreadyMappedTemplate(templateStringsKey, values) {
const elementKeys = extractElementKeys(values);
const nestedValue = getNestedValues(transformedTemplateStrings, [
templateStringsKey,
...elementKeys,
]);
return nestedValue.value?.template;
}
export function setMappedTemplate(templateStringsKey, values, valueToSet) {
const elementKeys = extractElementKeys(values);
return setNestedValues(transformedTemplateStrings, [
templateStringsKey,
...elementKeys,
], valueToSet);
}
function getNestedValues(map, keys, index = 0) {
const { currentTemplateAndNested, reason } = getCurrentKeyAndValue(map, keys, index);
if (!currentTemplateAndNested) {
return { value: currentTemplateAndNested, reason };
}
if (index === keys.length - 1) {
return { value: currentTemplateAndNested, reason: `reached end of keys array` };
}
if (!currentTemplateAndNested.nested) {
return { value: undefined, reason: `map at key index ${index} did not have nested maps` };
}
return getNestedValues(currentTemplateAndNested.nested, keys, index + 1);
}
function getCurrentKeyAndValue(map, keys, index) {
const currentKey = keys[index];
if (currentKey == undefined) {
return {
currentKey: undefined,
currentTemplateAndNested: undefined,
reason: `key at index ${index} not found`,
};
}
if (!map.has(currentKey)) {
return {
currentKey,
currentTemplateAndNested: undefined,
reason: `key at index ${index} was not in the map`,
};
}
const currentTemplateAndNested = map.get(currentKey);
if (currentTemplateAndNested == undefined) {
return {
currentKey,
currentTemplateAndNested: undefined,
reason: `value at key at index ${index} was undefined`,
};
}
return { currentKey, currentTemplateAndNested, reason: `key and value exists` };
}
function setNestedValues(map, keys, valueToSet, index = 0) {
const { currentTemplateAndNested, currentKey, reason } = getCurrentKeyAndValue(map, keys, index);
if (!currentKey) {
return { result: false, reason };
}
const nestedAndTemplate = currentTemplateAndNested ?? { nested: undefined, template: undefined };
if (!currentTemplateAndNested) {
map.set(currentKey, nestedAndTemplate);
}
if (index === keys.length - 1) {
nestedAndTemplate.template = valueToSet;
return { result: true, reason: `set value at end of keys array` };
}
const nestedWeakMap = nestedAndTemplate.nested ?? new WeakMap();
if (!nestedAndTemplate.nested) {
nestedAndTemplate.nested = nestedWeakMap;
}
return setNestedValues(nestedWeakMap, keys, valueToSet, index + 1);
}