UNPKG

webdash-readme-preview

Version:
157 lines (142 loc) 4.8 kB
/** @license Copyright (c) 2017 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ 'use strict'; import documentWait from './document-wait.js'; /** * @typedef {HTMLStyleElement | {getStyle: function():HTMLStyleElement}} */ export let CustomStyleProvider; const SEEN_MARKER = '__seenByShadyCSS'; const CACHED_STYLE = '__shadyCSSCachedStyle'; /** @type {?function(!HTMLStyleElement)} */ let transformFn = null; /** @type {?function()} */ let validateFn = null; /** This interface is provided to add document-level <style> elements to ShadyCSS for processing. These styles must be processed by ShadyCSS to simulate ShadowRoot upper-bound encapsulation from outside styles In addition, these styles may also need to be processed for @apply rules and CSS Custom Properties To add document-level styles to ShadyCSS, one can call `ShadyCSS.addDocumentStyle(styleElement)` or `ShadyCSS.addDocumentStyle({getStyle: () => styleElement})` In addition, if the process used to discover document-level styles can be synchronously flushed, one should set `ShadyCSS.documentStyleFlush`. This function will be called when calculating styles. An example usage of the document-level styling api can be found in `examples/document-style-lib.js` @unrestricted */ export default class CustomStyleInterface { constructor() { /** @type {!Array<!CustomStyleProvider>} */ this['customStyles'] = []; this['enqueued'] = false; } /** * Queue a validation for new custom styles to batch style recalculations */ enqueueDocumentValidation() { if (this['enqueued'] || !validateFn) { return; } this['enqueued'] = true; documentWait(validateFn); } /** * @param {!HTMLStyleElement} style */ addCustomStyle(style) { if (!style[SEEN_MARKER]) { style[SEEN_MARKER] = true; this['customStyles'].push(style); this.enqueueDocumentValidation(); } } /** * @param {!CustomStyleProvider} customStyle * @return {HTMLStyleElement} */ getStyleForCustomStyle(customStyle) { if (customStyle[CACHED_STYLE]) { return customStyle[CACHED_STYLE]; } let style; if (customStyle['getStyle']) { style = customStyle['getStyle'](); } else { style = customStyle; } return style; } /** * @return {!Array<!CustomStyleProvider>} */ processStyles() { const cs = this['customStyles']; for (let i = 0; i < cs.length; i++) { const customStyle = cs[i]; if (customStyle[CACHED_STYLE]) { continue; } const style = this.getStyleForCustomStyle(customStyle); if (style) { // HTMLImports polyfill may have cloned the style into the main document, // which is referenced with __appliedElement. const styleToTransform = /** @type {!HTMLStyleElement} */(style['__appliedElement'] || style); if (transformFn) { transformFn(styleToTransform); } customStyle[CACHED_STYLE] = styleToTransform; } } return cs; } } CustomStyleInterface.prototype['addCustomStyle'] = CustomStyleInterface.prototype.addCustomStyle; CustomStyleInterface.prototype['getStyleForCustomStyle'] = CustomStyleInterface.prototype.getStyleForCustomStyle; CustomStyleInterface.prototype['processStyles'] = CustomStyleInterface.prototype.processStyles; Object.defineProperties(CustomStyleInterface.prototype, { 'transformCallback': { /** @return {?function(!HTMLStyleElement)} */ get() { return transformFn; }, /** @param {?function(!HTMLStyleElement)} fn */ set(fn) { transformFn = fn; } }, 'validateCallback': { /** @return {?function()} */ get() { return validateFn; }, /** * @param {?function()} fn * @this {CustomStyleInterface} */ set(fn) { let needsEnqueue = false; if (!validateFn) { needsEnqueue = true; } validateFn = fn; if (needsEnqueue) { this.enqueueDocumentValidation(); } }, } }) /** @typedef {{ * customStyles: !Array<!CustomStyleProvider>, * addCustomStyle: function(!CustomStyleProvider), * getStyleForCustomStyle: function(!CustomStyleProvider): HTMLStyleElement, * findStyles: function(), * transformCallback: ?function(!HTMLStyleElement), * validateCallback: ?function() * }} */ export let CustomStyleInterfaceInterface;