@vaadin/vaadin-themable-mixin
Version:
vaadin-themable-mixin
100 lines (84 loc) • 2.89 kB
JavaScript
/**
* @license
* Copyright (c) 2021 - 2026 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { getLumoInjectorPropName, LumoInjector } from './src/lumo-injector.js';
/**
* @type {Set<string>}
*/
const registeredProperties = new Set();
/**
* Find enclosing root for given element to gather style rules from.
*
* @param {HTMLElement} element
* @return {DocumentOrShadowRoot}
*/
export function findRoot(element) {
const root = element.getRootNode();
if (root.host && root.host.constructor.version) {
return findRoot(root.host);
}
return root;
}
/**
* Mixin for internal use only. Do not use it in custom components.
*
* @polymerMixin
*/
export const LumoInjectionMixin = (superClass) =>
class LumoInjectionMixinClass extends superClass {
static finalize() {
super.finalize();
const propName = getLumoInjectorPropName(this.lumoInjector);
// Prevent registering same property twice when a class extends
// another class using this mixin, since `finalize()` is called
// by LitElement for all superclasses in the prototype chain.
if (this.is && !registeredProperties.has(propName)) {
registeredProperties.add(propName);
// Initialize custom property for this class with 0 as default
// so that changing it to 1 would inject styles to instances
// Use `inherits: true` so that property defined on `<html>`
// would apply to components instances within shadow roots
CSS.registerProperty({
name: propName,
syntax: '<number>',
inherits: true,
initialValue: '0',
});
}
}
static get lumoInjector() {
return {
is: this.is,
includeBaseStyles: false,
};
}
/** @protected */
connectedCallback() {
super.connectedCallback();
const root = findRoot(this);
// Do not initialize LumoInjector if it's disabled at the root.
// For example, Copilot does this because it uses its own styles
// on top of the base styles, and Lumo injection would interfere.
if (root.__lumoInjectorDisabled) {
return;
}
if (this.isConnected) {
root.__lumoInjector ||= new LumoInjector(root);
this.__lumoInjector = root.__lumoInjector;
this.__lumoInjector.componentConnected(this);
}
}
/** @protected */
disconnectedCallback() {
super.disconnectedCallback();
// Check if LumoInjector is defined. It might be unavailable if the component
// is moved within the DOM during connectedCallback and becomes disconnected
// before LumoInjector is assigned.
if (this.__lumoInjector) {
this.__lumoInjector.componentDisconnected(this);
this.__lumoInjector = undefined;
}
}
};