web/admin: bug: stage update forms not rendering, several modal form buttons missing (#20373)

## What

Names being passed to the browser were being incorrectly rendered. This commit updates the code in `StrictUnsafe` so that after the correct-use assertion is passed, the elementProperties are checked to see if the attribute has been named differently from the typed attribute field, and if so, retrieves the attribute name and passes it, rather than the field name, to the browser.

## Why

Since we have a lot of components with similar interfaces, it makes sense to try and check that they’re being used correctly and that the types associated with them are correct. Plus Lit, unlike React, doesn’t have a self-erasing syntax: every Lit element *is* an element, whereas JSX is an esoteric function call syntax that happens to look like XML. JavaScript templates aren’t as pretty as JSX, but they get the job done just as readily.

But in this case, cleverness bit us: we want to use the component’s JavaScript field names and types to validate that we’re using it correctly and passing the right types, but in the end we’re constructing a tag that will trigger the browser to construct the component and use it– and the field names don’t always correspond to the attribute name. Lit has a syntax for mapping the one to the other and stores it in the `elementProperties` field.

This code checks that, after we’ve determined the correct prefix for an property field that has been passed into the component, that we’ve also checked and extracted the correct *attribute name* for that property field. Most of the time it will be the same as the property field, but it muts always be checked.
This commit is contained in:
Ken Sternberg
2026-02-18 08:15:58 -08:00
committed by GitHub
parent 3ca055f3f4
commit d3b69b25f1
+9 -2
View File
@@ -63,16 +63,19 @@ export function StrictUnsafe<T extends CustomElementTagName>(
tagName: T,
props?: LitPropertyRecord<HTMLElementTagNameMap[T]>,
): SlottedTemplateResult;
export function StrictUnsafe<T extends AKElement>(
tagName: string,
props?: LitPropertyRecord<T>,
): SlottedTemplateResult;
export function StrictUnsafe<T extends string>(
tagName: string,
props?: T extends CustomElementTagName
? LitPropertyRecord<HTMLElementTagNameMap[T]>
: LitPropertyRecord<LitElement>,
): SlottedTemplateResult;
export function StrictUnsafe<T extends string>(
tagName: string,
props?: T extends CustomElementTagName
@@ -105,10 +108,14 @@ export function StrictUnsafe<T extends string>(
for (const [key, value] of Object.entries(props || {})) {
const propDeclaration = elementProperties.get(key);
if (propDeclaration) {
const prefix = getPrefix(propDeclaration.type, !propDeclaration.attribute);
filteredProps[`${prefix}${key}`] = value;
const name =
"attribute" in propDeclaration && typeof propDeclaration.attribute === "string"
? propDeclaration.attribute
: key;
filteredProps[`${prefix}${name}`] = value;
continue;
}