UNPKG

8.83 kBJavaScriptView Raw
1/**
2 * @license
3 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
4 * This code may only be used under the BSD style license found at
5 * http://polymer.github.io/LICENSE.txt
6 * The complete set of authors may be found at
7 * http://polymer.github.io/AUTHORS.txt
8 * The complete set of contributors may be found at
9 * http://polymer.github.io/CONTRIBUTORS.txt
10 * Code distributed by Google as part of the polymer project is also
11 * subject to an additional IP rights grant found at
12 * http://polymer.github.io/PATENTS.txt
13 */
14import { render } from 'lit-html/lib/shady-render.js';
15import { UpdatingElement } from './lib/updating-element.js';
16export * from './lib/updating-element.js';
17export * from './lib/decorators.js';
18export { html, svg, TemplateResult, SVGTemplateResult } from 'lit-html/lit-html.js';
19import { supportsAdoptingStyleSheets } from './lib/css-tag.js';
20export * from './lib/css-tag.js';
21// IMPORTANT: do not change the property name or the assignment expression.
22// This line will be used in regexes to search for LitElement usage.
23// TODO(justinfagnani): inject version number at build time
24(window['litElementVersions'] || (window['litElementVersions'] = []))
25 .push('2.3.1');
26/**
27 * Sentinal value used to avoid calling lit-html's render function when
28 * subclasses do not implement `render`
29 */
30const renderNotImplemented = {};
31export class LitElement extends UpdatingElement {
32 /**
33 * Return the array of styles to apply to the element.
34 * Override this method to integrate into a style management system.
35 *
36 * @nocollapse
37 */
38 static getStyles() {
39 return this.styles;
40 }
41 /** @nocollapse */
42 static _getUniqueStyles() {
43 // Only gather styles once per class
44 if (this.hasOwnProperty(JSCompiler_renameProperty('_styles', this))) {
45 return;
46 }
47 // Take care not to call `this.getStyles()` multiple times since this
48 // generates new CSSResults each time.
49 // TODO(sorvell): Since we do not cache CSSResults by input, any
50 // shared styles will generate new stylesheet objects, which is wasteful.
51 // This should be addressed when a browser ships constructable
52 // stylesheets.
53 const userStyles = this.getStyles();
54 if (userStyles === undefined) {
55 this._styles = [];
56 }
57 else if (Array.isArray(userStyles)) {
58 // De-duplicate styles preserving the _last_ instance in the set.
59 // This is a performance optimization to avoid duplicated styles that can
60 // occur especially when composing via subclassing.
61 // The last item is kept to try to preserve the cascade order with the
62 // assumption that it's most important that last added styles override
63 // previous styles.
64 const addStyles = (styles, set) => styles.reduceRight((set, s) =>
65 // Note: On IE set.add() does not return the set
66 Array.isArray(s) ? addStyles(s, set) : (set.add(s), set), set);
67 // Array.from does not work on Set in IE, otherwise return
68 // Array.from(addStyles(userStyles, new Set<CSSResult>())).reverse()
69 const set = addStyles(userStyles, new Set());
70 const styles = [];
71 set.forEach((v) => styles.unshift(v));
72 this._styles = styles;
73 }
74 else {
75 this._styles = [userStyles];
76 }
77 }
78 /**
79 * Performs element initialization. By default this calls `createRenderRoot`
80 * to create the element `renderRoot` node and captures any pre-set values for
81 * registered properties.
82 */
83 initialize() {
84 super.initialize();
85 this.constructor._getUniqueStyles();
86 this.renderRoot =
87 this.createRenderRoot();
88 // Note, if renderRoot is not a shadowRoot, styles would/could apply to the
89 // element's getRootNode(). While this could be done, we're choosing not to
90 // support this now since it would require different logic around de-duping.
91 if (window.ShadowRoot && this.renderRoot instanceof window.ShadowRoot) {
92 this.adoptStyles();
93 }
94 }
95 /**
96 * Returns the node into which the element should render and by default
97 * creates and returns an open shadowRoot. Implement to customize where the
98 * element's DOM is rendered. For example, to render into the element's
99 * childNodes, return `this`.
100 * @returns {Element|DocumentFragment} Returns a node into which to render.
101 */
102 createRenderRoot() {
103 return this.attachShadow({ mode: 'open' });
104 }
105 /**
106 * Applies styling to the element shadowRoot using the `static get styles`
107 * property. Styling will apply using `shadowRoot.adoptedStyleSheets` where
108 * available and will fallback otherwise. When Shadow DOM is polyfilled,
109 * ShadyCSS scopes styles and adds them to the document. When Shadow DOM
110 * is available but `adoptedStyleSheets` is not, styles are appended to the
111 * end of the `shadowRoot` to [mimic spec
112 * behavior](https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets).
113 */
114 adoptStyles() {
115 const styles = this.constructor._styles;
116 if (styles.length === 0) {
117 return;
118 }
119 // There are three separate cases here based on Shadow DOM support.
120 // (1) shadowRoot polyfilled: use ShadyCSS
121 // (2) shadowRoot.adoptedStyleSheets available: use it.
122 // (3) shadowRoot.adoptedStyleSheets polyfilled: append styles after
123 // rendering
124 if (window.ShadyCSS !== undefined && !window.ShadyCSS.nativeShadow) {
125 window.ShadyCSS.ScopingShim.prepareAdoptedCssText(styles.map((s) => s.cssText), this.localName);
126 }
127 else if (supportsAdoptingStyleSheets) {
128 this.renderRoot.adoptedStyleSheets =
129 styles.map((s) => s.styleSheet);
130 }
131 else {
132 // This must be done after rendering so the actual style insertion is done
133 // in `update`.
134 this._needsShimAdoptedStyleSheets = true;
135 }
136 }
137 connectedCallback() {
138 super.connectedCallback();
139 // Note, first update/render handles styleElement so we only call this if
140 // connected after first update.
141 if (this.hasUpdated && window.ShadyCSS !== undefined) {
142 window.ShadyCSS.styleElement(this);
143 }
144 }
145 /**
146 * Updates the element. This method reflects property values to attributes
147 * and calls `render` to render DOM via lit-html. Setting properties inside
148 * this method will *not* trigger another update.
149 * @param _changedProperties Map of changed properties with old values
150 */
151 update(changedProperties) {
152 // Setting properties in `render` should not trigger an update. Since
153 // updates are allowed after super.update, it's important to call `render`
154 // before that.
155 const templateResult = this.render();
156 super.update(changedProperties);
157 // If render is not implemented by the component, don't call lit-html render
158 if (templateResult !== renderNotImplemented) {
159 this.constructor
160 .render(templateResult, this.renderRoot, { scopeName: this.localName, eventContext: this });
161 }
162 // When native Shadow DOM is used but adoptedStyles are not supported,
163 // insert styling after rendering to ensure adoptedStyles have highest
164 // priority.
165 if (this._needsShimAdoptedStyleSheets) {
166 this._needsShimAdoptedStyleSheets = false;
167 this.constructor._styles.forEach((s) => {
168 const style = document.createElement('style');
169 style.textContent = s.cssText;
170 this.renderRoot.appendChild(style);
171 });
172 }
173 }
174 /**
175 * Invoked on each update to perform rendering tasks. This method may return
176 * any value renderable by lit-html's NodePart - typically a TemplateResult.
177 * Setting properties inside this method will *not* trigger the element to
178 * update.
179 */
180 render() {
181 return renderNotImplemented;
182 }
183}
184/**
185 * Ensure this class is marked as `finalized` as an optimization ensuring
186 * it will not needlessly try to `finalize`.
187 *
188 * Note this property name is a string to prevent breaking Closure JS Compiler
189 * optimizations. See updating-element.ts for more information.
190 */
191LitElement['finalized'] = true;
192/**
193 * Render method used to render the value to the element's DOM.
194 * @param result The value to render.
195 * @param container Node into which to render.
196 * @param options Element name.
197 * @nocollapse
198 */
199LitElement.render = render;
200//# sourceMappingURL=lit-element.js.map
\No newline at end of file