element-vir
Version:
Heroic. Reactive. Declarative. Type safe. Web components without compromise.
52 lines (51 loc) • 2.07 kB
JavaScript
import { getObjectTypedKeys } from '@augment-vir/common';
/**
* Which of an element's two property maps a value is being written to.
*
* @category Internal
*/
export var ElementPropertyType;
(function (ElementPropertyType) {
ElementPropertyType["Input"] = "input";
ElementPropertyType["State"] = "state";
})(ElementPropertyType || (ElementPropertyType = {}));
const collidingPropertyDescriptions = {
[ElementPropertyType.Input]: 'a state',
[ElementPropertyType.State]: 'an input',
};
export function createPropertyCollisionError({ propertyKey, propertyType, tagName, }) {
const lowerCasedTagName = tagName.toLowerCase();
return new Error(`Cannot set ${propertyType} '${String(propertyKey)}' on '${lowerCasedTagName}'. '${lowerCasedTagName}' already has ${collidingPropertyDescriptions[propertyType]} property with the same name.`);
}
export function assignInputs(element, inputs) {
const instanceState = element.instanceState;
const newInputKeys = getObjectTypedKeys(inputs);
/** Validate every key first so that a collision leaves the element untouched. */
newInputKeys.forEach((newInputKey) => {
if (instanceState && Object.hasOwn(instanceState, newInputKey)) {
throw createPropertyCollisionError({
propertyKey: newInputKey,
propertyType: ElementPropertyType.Input,
tagName: element.tagName,
});
}
});
newInputKeys.forEach((newInputKey) => {
if ('instanceInputs' in element) {
element.instanceInputs[newInputKey] =
inputs[newInputKey];
}
else {
element[newInputKey] = inputs[newInputKey];
}
});
/** Wipe out all inputs that weren't set to undefined (as expected) */
if ('instanceInputs' in element) {
getObjectTypedKeys(element.instanceInputs).forEach((existingKey) => {
if (!(existingKey in inputs)) {
element.instanceInputs[existingKey] =
undefined;
}
});
}
}