@logo-elements/polymer-legacy-adapter
Version:
A set of backwards compatibility adapters for Polymer Classic -specific legacy APIs for Logo Elements
131 lines (113 loc) • 4.5 kB
JavaScript
/**
* @license
* Copyright LOGO YAZILIM SANAYİ VE TİCARET A.Ş.
*
* Save to the extent permitted by law, you may not use, copy, modify,
* distribute or create derivative works of this material or any part
* of it without the prior written consent of LOGO YAZILIM SANAYİ VE TİCARET A.Ş. Limited.
* Any reproduction of this material must contain this notice.
*/
import { DomModule } from '@polymer/polymer/lib/elements/dom-module.js';
import { stylesFromTemplate } from '@polymer/polymer/lib/utils/style-gather.js';
import { unsafeCSS } from 'lit';
import { __themeRegistry as themeRegistry } from '@vaadin/vaadin-themable-mixin';
/**
* @typedef CSSResult
* @type {import('lit').CSSResult}
*
* @typedef DomModuleWithCachedStyles
* @type {DomModule & {__allStyles?: CSSResult[], __partialStyles?: CSSResult[]}}
*/
let moduleIdIndex = 0;
/**
* Registers CSS styles for a component type. Make sure to register the styles before
* the first instance of a component of the type is attached to DOM.
*
* @param {string} themeFor The local/tag name of the component type to register the styles for
* @param {CSSResult[]} styles The CSS style rules to be registered for the component type
* matching themeFor and included in the local scope of each component instance
* @param {{moduleId?: string, include?: string | string[]}} options Additional options
* @return {void}
*/
function registerStyles(themeFor, styles = [], options = {}) {
const themeId = options.moduleId || `custom-style-module-${moduleIdIndex++}`;
/** @type {DomModuleWithCachedStyles} */
const module = document.createElement('dom-module');
if (themeFor) {
module.setAttribute('theme-for', themeFor);
}
// The styles array only needs to be included in the template in case options.moduleId is used,
// so that it's possible to include the styles by moduleId in some other <dom-module>
// (with <style include="module-id">)
const includeStylesToTemplate = !!(styles.length && options.moduleId);
// options.include may be undefined, string or an array of strings. Convert it to an array
const moduleIncludes = [].concat(options.include || []);
if (moduleIncludes.length === 0) {
// No includes are used so the styles array is considered complete and can be cached as is
module.__allStyles = styles;
} else if (!includeStylesToTemplate) {
// Includes are used so the styles array can be cached,
// but the included styles must be later added on top of it.
// Don't cache anything in case the styles will get included in the
// <dom-module> template anyways to avoid duplicate styles.
module.__partialStyles = styles;
}
module.innerHTML = `
<template>
${moduleIncludes.map((include) => `<style include=${include}></style>`)}
${includeStylesToTemplate ? `<style>${styles.map((style) => style.cssText).join('\n')}</style>` : ''}
</template>
`;
module.register(themeId);
}
/**
* Returns an array of CSS results obtained from the style module
* @param {DomModule} module
* @returns {CSSResult[]}
*/
function getModuleStyles(module) {
return stylesFromTemplate(module.querySelector('template')).map((styleElement) => {
return unsafeCSS(styleElement.textContent);
});
}
/**
* @typedef {Object} Theme
* @property {string} themeFor
* @property {CSSResult[]} styles
* @property {string} [moduleId]
*/
/**
* Returns all the registered dom-modules mapped as themable-mixin -compatible Theme objects
* @returns {Theme[]}
*/
function getAllThemes() {
const domModule = DomModule;
const modules = domModule.prototype.modules;
return Object.keys(modules).map((moduleId) => {
/** @type {DomModuleWithCachedStyles} */
const module = modules[moduleId];
const themeFor = module.getAttribute('theme-for');
module.__allStyles = module.__allStyles || getModuleStyles(module).concat(module.__partialStyles || []);
return {
themeFor,
moduleId,
styles: module.__allStyles
};
});
}
window.LogoElements = window.LogoElements || {};
window.LogoElements.styleModules = {
getAllThemes,
registerStyles
};
// Convert any existing themes from the themable-mixin's themeRegistry to the style modules format
if (themeRegistry && themeRegistry.length > 0) {
themeRegistry.forEach((theme) => {
registerStyles(theme.themeFor, theme.styles, {
moduleId: theme.moduleId,
include: theme.include
});
});
// Clear the themeRegistry
themeRegistry.length = 0;
}