UNPKG

element-vir

Version:

Heroic. Reactive. Declarative. Type safe. Web components without compromise.

119 lines (118 loc) 4.03 kB
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; } else 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, }; } else if (index === keys.length - 1) { return { value: currentTemplateAndNested, reason: 'reached end of keys array', }; } else 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`, }; } else 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); }