New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@vaadin/vaadin-themable-mixin

Package Overview
Dependencies
Maintainers
19
Versions
501
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vaadin/vaadin-themable-mixin - npm Package Compare versions

Comparing version 22.0.0-alpha6 to 22.0.0-alpha7

42

package.json
{
"name": "@vaadin/vaadin-themable-mixin",
"version": "22.0.0-alpha6",
"version": "22.0.0-alpha7",
"publishConfig": {
"access": "public"
},
"description": "vaadin-themable-mixin",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/vaadin/web-components.git",
"directory": "packages/vaadin-themable-mixin"
},
"author": "Vaadin Ltd",
"homepage": "https://vaadin.com/elements",
"bugs": {
"url": "https://github.com/vaadin/vaadin-themable-mixin/issues"
},
"main": "vaadin-themable-mixin.js",
"module": "vaadin-themable-mixin.js",
"repository": "vaadin/vaadin-themable-mixin",
"files": [
"*.d.ts",
"register-styles.js",
"vaadin-*.js"
],
"keywords": [

@@ -14,26 +32,12 @@ "Vaadin",

],
"author": "Vaadin Ltd",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/vaadin/vaadin-themable-mixin/issues"
},
"homepage": "https://vaadin.com/elements",
"files": [
"*.d.ts",
"vaadin-*.js",
"register-styles.js"
],
"dependencies": {
"@polymer/polymer": "^3.0.0",
"lit": "^2.0.0-rc.1"
"lit": "^2.0.0"
},
"devDependencies": {
"@esm-bundle/chai": "^4.3.4",
"@polymer/polymer": "^3.0.0",
"@vaadin/testing-helpers": "^0.3.0",
"sinon": "^9.2.4"
},
"publishConfig": {
"access": "public"
},
"gitHead": "4b136b1c7da8942960e7255f40c27859125b3a45"
"gitHead": "8e89419c6b44a1d225d5859e180d7b35e47ddb52"
}

@@ -1,11 +0,6 @@

import { CSSResultGroup } from 'lit';
export { css, unsafeCSS } from 'lit';
/**
* 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.
* @license
* Copyright (c) 2021 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
declare function registerStyles(themeFor: string | null, styles: CSSResultGroup, options?: object | null): void;
export { registerStyles };
export { registerStyles, css, unsafeCSS } from './vaadin-themable-mixin.js';

@@ -1,80 +0,6 @@

import '@polymer/polymer/lib/elements/dom-module.js';
import { CSSResult } from 'lit';
import { stylesFromTemplate } from '@polymer/polymer/lib/utils/style-gather.js';
export { css, unsafeCSS } from 'lit';
let moduleIdIndex = 0;
// Map of <CSSResult, Polymer.DomModule> pairs.
const styleMap = {};
function recursiveFlattenStyles(styles, result = []) {
if (styles instanceof CSSResult) {
result.push(styles);
} else if (Array.isArray(styles)) {
styles.forEach((style) => recursiveFlattenStyles(style, result));
}
return result;
}
/**
* 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 {CSSResultGroup} 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 {Object=} options Additional options
* @return {void}
* @license
* Copyright (c) 2021 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
export const registerStyles = (themeFor, styles, options) => {
if (options && options.include && !options.suppressDeprecationWarning) {
console.warn(
`The "include" option in registerStyles is deprecated. Instead, include an imported CSSResult in the styles array.`
);
}
const themeId = (options && options.moduleId) || `custom-style-module-${moduleIdIndex++}`;
if (!Array.isArray(styles)) {
styles = styles ? [styles] : [];
}
styles = recursiveFlattenStyles(styles);
const processedStyles = styles.map((cssResult) => {
if (!(cssResult instanceof CSSResult)) {
throw new Error('An item in styles is not of type CSSResult. Use `unsafeCSS` or `css`.');
}
if (!styleMap[cssResult]) {
const template = document.createElement('template');
template.innerHTML = `<style>${cssResult.toString()}</style>`;
styleMap[cssResult] = stylesFromTemplate(template)[0];
}
return styleMap[cssResult].textContent;
});
const themeModuleElement = document.createElement('dom-module');
if (themeFor) {
const elementClass = customElements.get(themeFor);
if (elementClass && Object.prototype.hasOwnProperty.call(elementClass, '__finalized')) {
console.warn(`The custom element definition for "${themeFor}"
was finalized before a style module was registered.
Make sure to add component specific style modules before
importing the corresponding custom element.`);
}
themeModuleElement.setAttribute('theme-for', themeFor);
}
const moduleIncludes = (options && options.include) || [];
themeModuleElement.innerHTML = `
<template>
${moduleIncludes.map((include) => `<style include=${include}></style>`)}
${processedStyles.length ? `<style>${processedStyles.join('\n')}</style>` : ''}
</template>
`;
themeModuleElement.register(themeId);
};
export { registerStyles, css, unsafeCSS } from './vaadin-themable-mixin.js';

@@ -0,1 +1,7 @@

/**
* @license
* Copyright (c) 2021 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { CSSResult, CSSResultGroup } from 'lit';
import { ThemePropertyMixin, ThemePropertyMixinConstructor } from './vaadin-theme-property-mixin.js';

@@ -14,2 +20,22 @@

export { ThemableMixin, ThemableMixinConstructor };
/**
* 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.
*/
declare function registerStyles(themeFor: string | null, styles: CSSResultGroup, options?: object | null): void;
type Theme = {
themeFor: string;
styles: CSSResult[];
moduleId?: string;
include?: string | string[];
};
/**
* For internal purposes only.
*/
declare const __themeRegistry: Theme[];
export { css, unsafeCSS } from 'lit';
export { ThemableMixin, ThemableMixinConstructor, registerStyles, __themeRegistry };

@@ -1,5 +0,185 @@

import { DomModule } from '@polymer/polymer/lib/elements/dom-module.js';
/**
* @license
* Copyright (c) 2021 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { CSSResult, css, unsafeCSS } from 'lit';
import { ThemePropertyMixin } from './vaadin-theme-property-mixin.js';
export { css, unsafeCSS };
/**
* @typedef {Object} Theme
* @property {string} themeFor
* @property {CSSResult[]} styles
* @property {string | string[]} [include]
* @property {string} [moduleId]
*
* @typedef {CSSResult[] | CSSResult} CSSResultGroup
*/
/**
* @type {Theme[]}
*/
const themeRegistry = [];
/**
* 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 {CSSResultGroup} 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}
*/
export function registerStyles(themeFor, styles, options = {}) {
if (themeFor) {
const elementClass = customElements.get(themeFor);
if (elementClass && Object.prototype.hasOwnProperty.call(elementClass, '__finalized')) {
console.warn(`The custom element definition for "${themeFor}"
was finalized before a style module was registered.
Make sure to add component specific style modules before
importing the corresponding custom element.`);
}
}
styles = recursiveFlattenStyles(styles);
if (window.Vaadin && window.Vaadin.styleModules) {
window.Vaadin.styleModules.registerStyles(themeFor, styles, options);
} else {
themeRegistry.push({
themeFor,
styles,
include: options.include,
moduleId: options.moduleId
});
}
}
/**
* Returns all registered themes. By default the themeRegistry is returend as is.
* In case the style-modules adapter is imported, the themes are obtained from there instead
* @returns {Theme[]}
*/
function getAllThemes() {
if (window.Vaadin && window.Vaadin.styleModules) {
return window.Vaadin.styleModules.getAllThemes();
} else {
return themeRegistry;
}
}
/**
* Returns true if the themeFor string matches the tag name
* @param {string} themeFor
* @param {string} tagName
* @returns {boolean}
*/
function matchesThemeFor(themeFor, tagName) {
return (themeFor || '').split(' ').some((themeForToken) => {
return new RegExp('^' + themeForToken.split('*').join('.*') + '$').test(tagName);
});
}
/**
* Maps the moduleName to an include priority number which is used for
* determining the order in which styles are applied.
* @param {string} moduleName
* @returns {number}
*/
function getIncludePriority(moduleName = '') {
let includePriority = 0;
if (moduleName.indexOf('lumo-') === 0 || moduleName.indexOf('material-') === 0) {
includePriority = 1;
} else if (moduleName.indexOf('vaadin-') === 0) {
includePriority = 2;
}
return includePriority;
}
/**
* Flattens the styles into a single array of styles.
* @param {CSSResultGroup} styles
* @param {CSSResult[]} result
* @returns {CSSResult[]}
*/
function recursiveFlattenStyles(styles = [], result = []) {
if (styles instanceof CSSResult) {
result.push(styles);
} else if (Array.isArray(styles)) {
styles.forEach((style) => recursiveFlattenStyles(style, result));
} else {
console.warn('An item in styles is not of type CSSResult. Use `unsafeCSS` or `css`.');
}
return result;
}
/**
* Gets an array of CSSResults matching the include property of the theme.
* @param {Theme} theme
* @returns {CSSResult[]}
*/
function getIncludedStyles(theme) {
const includedStyles = [];
if (theme.include) {
[].concat(theme.include).forEach((includeModuleId) => {
const includedTheme = getAllThemes().find((s) => s.moduleId === includeModuleId);
if (includedTheme) {
includedStyles.push(...getIncludedStyles(includedTheme), ...includedTheme.styles);
} else {
console.warn(`Included moduleId ${includeModuleId} not found in style registry`);
}
}, theme.styles);
}
return includedStyles;
}
/**
* Includes the styles to the template.
* @param {CSSResult[]} styles
* @param {HTMLTemplateElement} template
*/
function addStylesToTemplate(styles, template) {
const styleEl = document.createElement('style');
styleEl.innerHTML = styles
// Remove duplicates so that the last occurrence remains
.filter((style, index) => index === styles.lastIndexOf(style))
.map((style) => style.cssText)
.join('\n');
template.content.appendChild(styleEl);
}
/**
* Returns an array of themes that should be used for styling a component matching
* the tag name. The array is sorted by the include order.
* @param {string} tagName
* @returns {Theme[]}
*/
function getThemes(tagName) {
const defaultModuleName = tagName + '-default-theme';
const themes = getAllThemes()
// Filter by matching themeFor properties
.filter((theme) => theme.moduleId !== defaultModuleName && matchesThemeFor(theme.themeFor, tagName))
.map((theme) => ({
...theme,
// Prepend styles from included themes
styles: [...getIncludedStyles(theme), ...theme.styles],
// Map moduleId to includePriority
includePriority: getIncludePriority(theme.moduleId)
}))
// Sort by includePriority
.sort((themeA, themeB) => themeB.includePriority - themeA.includePriority);
if (themes.length > 0) {
return themes;
} else {
// No theme modules found, return the default module if it exists
return getAllThemes().filter((theme) => theme.moduleId === defaultModuleName);
}
}
/**
* @polymerMixin

@@ -10,3 +190,6 @@ * @mixes ThemePropertyMixin

class VaadinThemableMixin extends ThemePropertyMixin(superClass) {
/** @protected */
/**
* Covers PolymerElement based component styling
* @protected
*/
static finalize() {

@@ -16,70 +199,34 @@ super.finalize();

const template = this.prototype._template;
if (!template || template.__themes) {
return;
}
const inheritedTemplate = Object.getPrototypeOf(this.prototype)._template;
if (inheritedTemplate) {
// Include the theme modules from the inherited template
Array.from(inheritedTemplate.content.querySelectorAll('style[include]')).forEach((s) => {
this._includeStyle(s.getAttribute('include'), template);
});
}
const inheritedThemes = (inheritedTemplate ? inheritedTemplate.__themes : []) || [];
this._includeMatchingThemes(template);
}
template.__themes = [...inheritedThemes, ...getThemes(this.is)];
/** @private */
static _includeMatchingThemes(template) {
const domModule = DomModule;
const modules = domModule.prototype.modules;
let hasThemes = false;
const defaultModuleName = this.is + '-default-theme';
Object.keys(modules)
.sort((moduleNameA, moduleNameB) => {
const vaadinA = moduleNameA.indexOf('vaadin-') === 0;
const vaadinB = moduleNameB.indexOf('vaadin-') === 0;
const vaadinThemePrefixes = ['lumo-', 'material-'];
const vaadinThemeA = vaadinThemePrefixes.filter((prefix) => moduleNameA.indexOf(prefix) === 0).length > 0;
const vaadinThemeB = vaadinThemePrefixes.filter((prefix) => moduleNameB.indexOf(prefix) === 0).length > 0;
if (vaadinA !== vaadinB) {
// Include vaadin core styles first
return vaadinA ? -1 : 1;
} else if (vaadinThemeA !== vaadinThemeB) {
// Include vaadin theme styles after that
return vaadinThemeA ? -1 : 1;
} else {
// Lastly include custom styles so they override all vaadin styles
return 0;
}
})
.forEach((moduleName) => {
if (moduleName !== defaultModuleName) {
const themeFor = modules[moduleName].getAttribute('theme-for');
if (themeFor) {
themeFor.split(' ').forEach((themeForToken) => {
if (new RegExp('^' + themeForToken.split('*').join('.*') + '$').test(this.is)) {
hasThemes = true;
this._includeStyle(moduleName, template);
}
});
}
}
});
if (!hasThemes && modules[defaultModuleName]) {
// No theme modules found, include the default module if it exists
this._includeStyle(defaultModuleName, template);
}
// Get flattened styles array
const styles = template.__themes.reduce((styles, theme) => [...styles, ...theme.styles], []);
addStylesToTemplate(styles, template);
}
/** @private */
static _includeStyle(moduleName, template) {
if (template && !template.content.querySelector(`style[include="${moduleName}"]`)) {
const styleEl = document.createElement('style');
styleEl.setAttribute('include', moduleName);
template.content.appendChild(styleEl);
}
/**
* Covers LitElement based component styling
*
* NOTE: This is not yet an offically supported API!
*
* TODO: Add tests (run a variation of themable-mixin.test.js where the components get created as LitElements)
* @protected
*/
static finalizeStyles(styles) {
return (
getThemes(this.is)
// Get flattened styles array
.reduce((styles, theme) => [...styles, ...theme.styles], [])
.concat(styles)
);
}
};
export { themeRegistry as __themeRegistry };

@@ -0,1 +1,6 @@

/**
* @license
* Copyright (c) 2021 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
declare function ThemePropertyMixin<T extends new (...args: any[]) => {}>(base: T): T & ThemePropertyMixinConstructor;

@@ -2,0 +7,0 @@

/**
* @license
* Copyright (c) 2021 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
/**
* @polymerMixin

@@ -3,0 +8,0 @@ */

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc