I have a decorator to inject my common stylesheets into lit components written with the legacy 2018 proposal (as what was previously supported by lit). Upgrading to lit 3, they changed to the 2023-05 proposal and my decorator no longer works. How do I update my decorator to the 2023-05 proposal?
My understanding is fields no longer have initializers, so I'm not sure how to do this now:
Decorator
const injectTheme = (...styles) => (target) => {
const { initializer } = target;
// Inject tailwind
let newStyles = [tailwind];
// Add any initial styles into the new style array
if (initializer) {
const initStyles = initializer.call(this);
if (Array.isArray(initStyles)) {
newStyles.push(...initStyles);
} else {
newStyles.push(initStyles);
}
}
// Add passed in styles last
newStyles.push(...styles);
// Remove any invalid styles
newStyles = newStyles.filter((style) => !!style);
// Ensure that they are valid style sheets
newStyles = newStyles.map(assertCSS);
// Override initializer to return new styles array
target.initializer = function () {
return newStyles;
};
};
Example Usage
import styles from './styles.css';
@customElement('my-element')
class MyElement extends LitElement {
@injectTheme(styles) static styles;
}
Preferred Syntax
Is it possible to make this a class decorator as I think I'd prefer that. Only issue I see is that class decorators are called after the static elements are assigned:
Class decorator initializers are run after the class has been fully defined, and after class static fields have been assigned.
@injectTheme(style)
@customElement('my-element')
class MyElement extends LitElement {
}
Figured out how to convert the functionality to the new proposal. I`m still curious if its possible to do this as a class decorator.
The decorator can return a function, which takes in the initial value (initalStyles) and can return a modified value.