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 */ 14/** 15 * True if the custom elements polyfill is in use. 16 */ 17const isCEPolyfill = typeof window !== 'undefined' && 18 window.customElements != null && 19 window.customElements.polyfillWrapFlushCallback !== 20 undefined; 21/** 22 * Removes nodes, starting from `start` (inclusive) to `end` (exclusive), from 23 * `container`. 24 */ 25const removeNodes = (container, start, end = null) => { 26 while (start !== end) { 27 const n = start.nextSibling; 28 container.removeChild(start); 29 start = n; 30 } 31}; 32 33/** 34 * @license 35 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 36 * This code may only be used under the BSD style license found at 37 * http://polymer.github.io/LICENSE.txt 38 * The complete set of authors may be found at 39 * http://polymer.github.io/AUTHORS.txt 40 * The complete set of contributors may be found at 41 * http://polymer.github.io/CONTRIBUTORS.txt 42 * Code distributed by Google as part of the polymer project is also 43 * subject to an additional IP rights grant found at 44 * http://polymer.github.io/PATENTS.txt 45 */ 46/** 47 * An expression marker with embedded unique key to avoid collision with 48 * possible text in templates. 49 */ 50const marker = `{{lit-${String(Math.random()).slice(2)}}}`; 51/** 52 * An expression marker used text-positions, multi-binding attributes, and 53 * attributes with markup-like text values. 54 */ 55const nodeMarker = `<!--${marker}-->`; 56const markerRegex = new RegExp(`${marker}|${nodeMarker}`); 57/** 58 * Suffix appended to all bound attribute names. 59 */ 60const boundAttributeSuffix = '$lit$'; 61/** 62 * An updatable Template that tracks the location of dynamic parts. 63 */ 64class Template { 65 constructor(result, element) { 66 this.parts = []; 67 this.element = element; 68 const nodesToRemove = []; 69 const stack = []; 70 // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null 71 const walker = document.createTreeWalker(element.content, 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */, null, false); 72 // Keeps track of the last index associated with a part. We try to delete
vendor: 7,052 bytes, lines 73-209
73 // unnecessary nodes, but we never want to associate two different parts 74 // to the same index. They must have a constant node between. 75 let lastPartIndex = 0; 76 let index = -1; 77 let partIndex = 0; 78 const { strings, values: { length } } = result; 79 while (partIndex < length) { 80 const node = walker.nextNode(); 81 if (node === null) { 82 // We've exhausted the content inside a nested template element. 83 // Because we still have parts (the outer for-loop), we know: 84 // - There is a template in the stack 85 // - The walker will find a nextNode outside the template 86 walker.currentNode = stack.pop(); 87 continue; 88 } 89 index++; 90 if (node.nodeType === 1 /* Node.ELEMENT_NODE */) { 91 if (node.hasAttributes()) { 92 const attributes = node.attributes; 93 const { length } = attributes; 94 // Per 95 // https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap, 96 // attributes are not guaranteed to be returned in document order. 97 // In particular, Edge/IE can return them out of order, so we cannot 98 // assume a correspondence between part index and attribute index. 99 let count = 0; 100 for (let i = 0; i < length; i++) { 101 if (endsWith(attributes[i].name, boundAttributeSuffix)) { 102 count++; 103 } 104 } 105 while (count-- > 0) { 106 // Get the template literal section leading up to the first 107 // expression in this attribute 108 const stringForPart = strings[partIndex]; 109 // Find the attribute name 110 const name = lastAttributeNameRegex.exec(stringForPart)[2]; 111 // Find the corresponding attribute 112 // All bound attributes have had a suffix added in 113 // TemplateResult#getHTML to opt out of special attribute 114 // handling. To look up the attribute value we also need to add 115 // the suffix. 116 const attributeLookupName = name.toLowerCase() + boundAttributeSuffix; 117 const attributeValue = node.getAttribute(attributeLookupName); 118 node.removeAttribute(attributeLookupName); 119 const statics = attributeValue.split(markerRegex); 120 this.parts.push({ type: 'attribute', index, name, strings: statics }); 121 partIndex += statics.length - 1; 122 } 123 } 124 if (node.tagName === 'TEMPLATE') { 125 stack.push(node); 126 walker.currentNode = node.content; 127 } 128 } 129 else if (node.nodeType === 3 /* Node.TEXT_NODE */) { 130 const data = node.data; 131 if (data.indexOf(marker) >= 0) { 132 const parent = node.parentNode; 133 const strings = data.split(markerRegex); 134 const lastIndex = strings.length - 1; 135 // Generate a new text node for each literal section 136 // These nodes are also used as the markers for node parts 137 for (let i = 0; i < lastIndex; i++) { 138 let insert; 139 let s = strings[i]; 140 if (s === '') { 141 insert = createMarker(); 142 } 143 else { 144 const match = lastAttributeNameRegex.exec(s); 145 if (match !== null && endsWith(match[2], boundAttributeSuffix)) { 146 s = s.slice(0, match.index) + match[1] + 147 match[2].slice(0, -boundAttributeSuffix.length) + match[3]; 148 } 149 insert = document.createTextNode(s); 150 } 151 parent.insertBefore(insert, node); 152 this.parts.push({ type: 'node', index: ++index }); 153 } 154 // If there's no text, we must insert a comment to mark our place. 155 // Else, we can trust it will stick around after cloning. 156 if (strings[lastIndex] === '') { 157 parent.insertBefore(createMarker(), node); 158 nodesToRemove.push(node); 159 } 160 else { 161 node.data = strings[lastIndex]; 162 } 163 // We have a part for each match found 164 partIndex += lastIndex; 165 } 166 } 167 else if (node.nodeType === 8 /* Node.COMMENT_NODE */) { 168 if (node.data === marker) { 169 const parent = node.parentNode; 170 // Add a new marker node to be the startNode of the Part if any of 171 // the following are true: 172 // * We don't have a previousSibling 173 // * The previousSibling is already the start of a previous part 174 if (node.previousSibling === null || index === lastPartIndex) { 175 index++; 176 parent.insertBefore(createMarker(), node); 177 } 178 lastPartIndex = index; 179 this.parts.push({ type: 'node', index }); 180 // If we don't have a nextSibling, keep this node so we have an end. 181 // Else, we can remove it to save future costs. 182 if (node.nextSibling === null) { 183 node.data = ''; 184 } 185 else { 186 nodesToRemove.push(node); 187 index--; 188 } 189 partIndex++; 190 } 191 else { 192 let i = -1; 193 while ((i = node.data.indexOf(marker, i + 1)) !== -1) { 194 // Comment node has a binding marker inside, make an inactive part 195 // The binding won't work, but subsequent bindings will 196 // TODO (justinfagnani): consider whether it's even worth it to 197 // make bindings in comments work 198 this.parts.push({ type: 'node', index: -1 }); 199 partIndex++; 200 } 201 } 202 } 203 } 204 // Remove text binding nodes after the walk to not disturb the TreeWalker 205 for (const n of nodesToRemove) { 206 n.parentNode.removeChild(n); 207 } 208 } 209}
210const endsWith = (str, suffix) => { 211 const index = str.length - suffix.length; 212 return index >= 0 && str.slice(index) === suffix; 213}; 214const isTemplatePartActive = (part) => part.index !== -1; 215// Allows `document.createComment('')` to be renamed for a 216// small manual size-savings. 217const createMarker = () => document.createComment(''); 218/** 219 * This regex extracts the attribute name preceding an attribute-position 220 * expression. It does this by matching the syntax allowed for attributes 221 * against the string literal directly preceding the expression, assuming that 222 * the expression is in an attribute-value position. 223 * 224 * See attributes in the HTML spec: 225 * https://www.w3.org/TR/html5/syntax.html#elements-attributes 226 * 227 * " \x09\x0a\x0c\x0d" are HTML space characters: 228 * https://www.w3.org/TR/html5/infrastructure.html#space-characters 229 * 230 * "\0-\x1F\x7F-\x9F" are Unicode control characters, which includes every 231 * space character except " ". 232 * 233 * So an attribute is: 234 * * The name: any character except a control character, space character, ('), 235 * ("), ">", "=", or "/" 236 * * Followed by zero or more space characters 237 * * Followed by "=" 238 * * Followed by zero or more space characters 239 * * Followed by: 240 * * Any character except space, ('), ("), "<", ">", "=", (`), or 241 * * (") then any non-("), or 242 * * (') then any non-(') 243 */ 244const lastAttributeNameRegex = 245// eslint-disable-next-line no-control-regex 246/([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/; 247 248/** 249 * @license 250 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 251 * This code may only be used under the BSD style license found at 252 * http://polymer.github.io/LICENSE.txt 253 * The complete set of authors may be found at 254 * http://polymer.github.io/AUTHORS.txt 255 * The complete set of contributors may be found at 256 * http://polymer.github.io/CONTRIBUTORS.txt 257 * Code distributed by Google as part of the polymer project is also 258 * subject to an additional IP rights grant found at 259 * http://polymer.github.io/PATENTS.txt 260 */ 261const walkerNodeFilter = 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */; 262/** 263 * Removes the list of nodes from a Template safely. In addition to removing 264 * nodes from the Template, the Template part indices are updated to match 265 * the mutated Template DOM. 266 * 267 * As the template is walked the removal state is tracked and 268 * part indices are adjusted as needed. 269 * 270 * div 271 * div#1 (remove) <-- start removing (removing node is div#1) 272 * div 273 * div#2 (remove) <-- continue removing (removing node is still div#1) 274 * div 275 * div <-- stop removing since previous sibling is the removing node (div#1, 276 * removed 4 nodes) 277 */ 278function removeNodesFromTemplate(template, nodesToRemove) { 279 const { element: { content }, parts } = template; 280 const walker = document.createTreeWalker(content, walkerNodeFilter, null, false); 281 let partIndex = nextActiveIndexInTemplateParts(parts); 282 let part = parts[partIndex]; 283 let nodeIndex = -1; 284 let removeCount = 0; 285 const nodesToRemoveInTemplate = []; 286 let currentRemovingNode = null; 287 while (walker.nextNode()) { 288 nodeIndex++; 289 const node = walker.currentNode; 290 // End removal if stepped past the removing node 291 if (node.previousSibling === currentRemovingNode) { 292 currentRemovingNode = null; 293 } 294 // A node to remove was found in the template 295 if (nodesToRemove.has(node)) { 296 nodesToRemoveInTemplate.push(node); 297 // Track node we're removing 298 if (currentRemovingNode === null) { 299 currentRemovingNode = node; 300 } 301 } 302 // When removing, increment count by which to adjust subsequent part indices 303 if (currentRemovingNode !== null) { 304 removeCount++; 305 } 306 while (part !== undefined && part.index === nodeIndex) { 307 // If part is in a removed node deactivate it by setting index to -1 or 308 // adjust the index as needed. 309 part.index = currentRemovingNode !== null ? -1 : part.index - removeCount; 310 // go to the next active part. 311 partIndex = nextActiveIndexInTemplateParts(parts, partIndex); 312 part = parts[partIndex]; 313 } 314 } 315 nodesToRemoveInTemplate.forEach((n) => n.parentNode.removeChild(n)); 316} 317const countNodes = (node) => {
318 let count = (node.nodeType === 11 /* Node.DOCUMENT_FRAGMENT_NODE */) ? 0 : 1; 319 const walker = document.createTreeWalker(node, walkerNodeFilter, null, false); 320 while (walker.nextNode()) { 321 count++; 322 } 323 return count; 324}; 325const nextActiveIndexInTemplateParts = (parts, startIndex = -1) => { 326 for (let i = startIndex + 1; i < parts.length; i++) { 327 const part = parts[i]; 328 if (isTemplatePartActive(part)) { 329 return i; 330 } 331 } 332 return -1; 333}; 334/** 335 * Inserts the given node into the Template, optionally before the given 336 * refNode. In addition to inserting the node into the Template, the Template 337 * part indices are updated to match the mutated Template DOM. 338 */ 339function insertNodeIntoTemplate(template, node, refNode = null) { 340 const { element: { content }, parts } = template; 341 // If there's no refNode, then put node at end of template. 342 // No part indices need to be shifted in this case. 343 if (refNode === null || refNode === undefined) { 344 content.appendChild(node); 345 return; 346 } 347 const walker = document.createTreeWalker(content, walkerNodeFilter, null, false); 348 let partIndex = nextActiveIndexInTemplateParts(parts); 349 let insertCount = 0; 350 let walkerIndex = -1; 351 while (walker.nextNode()) { 352 walkerIndex++; 353 const walkerNode = walker.currentNode; 354 if (walkerNode === refNode) { 355 insertCount = countNodes(node); 356 refNode.parentNode.insertBefore(node, refNode); 357 } 358 while (partIndex !== -1 && parts[partIndex].index === walkerIndex) { 359 // If we've inserted the node, simply adjust all subsequent parts 360 if (insertCount > 0) { 361 while (partIndex !== -1) { 362 parts[partIndex].index += insertCount; 363 partIndex = nextActiveIndexInTemplateParts(parts, partIndex); 364 } 365 return; 366 } 367 partIndex = nextActiveIndexInTemplateParts(parts, partIndex); 368 } 369 } 370} 371 372/** 373 * @license 374 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 375 * This code may only be used under the BSD style license found at 376 * http://polymer.github.io/LICENSE.txt 377 * The complete set of authors may be found at 378 * http://polymer.github.io/AUTHORS.txt 379 * The complete set of contributors may be found at 380 * http://polymer.github.io/CONTRIBUTORS.txt 381 * Code distributed by Google as part of the polymer project is also 382 * subject to an additional IP rights grant found at 383 * http://polymer.github.io/PATENTS.txt 384 */ 385const directives = new WeakMap(); 386const isDirective = (o) => { 387 return typeof o === 'function' && directives.has(o); 388}; 389 390/** 391 * @license 392 * Copyright (c) 2018 The Polymer Project Authors. All rights reserved. 393 * This code may only be used under the BSD style license found at 394 * http://polymer.github.io/LICENSE.txt 395 * The complete set of authors may be found at 396 * http://polymer.github.io/AUTHORS.txt 397 * The complete set of contributors may be found at 398 * http://polymer.github.io/CONTRIBUTORS.txt 399 * Code distributed by Google as part of the polymer project is also 400 * subject to an additional IP rights grant found at 401 * http://polymer.github.io/PATENTS.txt 402 */ 403/** 404 * A sentinel value that signals that a value was handled by a directive and 405 * should not be written to the DOM. 406 */ 407const noChange = {}; 408/** 409 * A sentinel value that signals a NodePart to fully clear its content. 410 */ 411const nothing = {}; 412 413/** 414 * @license 415 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 416 * This code may only be used under the BSD style license found at 417 * http://polymer.github.io/LICENSE.txt 418 * The complete set of authors may be found at 419 * http://polymer.github.io/AUTHORS.txt 420 * The complete set of contributors may be found at 421 * http://polymer.github.io/CONTRIBUTORS.txt 422 * Code distributed by Google as part of the polymer project is also 423 * subject to an additional IP rights grant found at 424 * http://polymer.github.io/PATENTS.txt 425 */ 426/** 427 * An instance of a `Template` that can be attached to the DOM and updated
428 * with new values. 429 */ 430class TemplateInstance { 431 constructor(template, processor, options) { 432 this.__parts = []; 433 this.template = template; 434 this.processor = processor; 435 this.options = options; 436 } 437 update(values) { 438 let i = 0; 439 for (const part of this.__parts) { 440 if (part !== undefined) { 441 part.setValue(values[i]); 442 } 443 i++; 444 } 445 for (const part of this.__parts) { 446 if (part !== undefined) { 447 part.commit(); 448 } 449 } 450 } 451 _clone() { 452 // There are a number of steps in the lifecycle of a template instance's 453 // DOM fragment: 454 // 1. Clone - create the instance fragment 455 // 2. Adopt - adopt into the main document 456 // 3. Process - find part markers and create parts 457 // 4. Upgrade - upgrade custom elements 458 // 5. Update - set node, attribute, property, etc., values 459 // 6. Connect - connect to the document. Optional and outside of this 460 // method. 461 // 462 // We have a few constraints on the ordering of these steps: 463 // * We need to upgrade before updating, so that property values will pass 464 // through any property setters. 465 // * We would like to process before upgrading so that we're sure that the 466 // cloned fragment is inert and not disturbed by self-modifying DOM. 467 // * We want custom elements to upgrade even in disconnected fragments. 468 // 469 // Given these constraints, with full custom elements support we would 470 // prefer the order: Clone, Process, Adopt, Upgrade, Update, Connect 471 // 472 // But Safari does not implement CustomElementRegistry#upgrade, so we 473 // can not implement that order and still have upgrade-before-update and 474 // upgrade disconnected fragments. So we instead sacrifice the 475 // process-before-upgrade constraint, since in Custom Elements v1 elements 476 // must not modify their light DOM in the constructor. We still have issues 477 // when co-existing with CEv0 elements like Polymer 1, and with polyfills 478 // that don't strictly adhere to the no-modification rule because shadow 479 // DOM, which may be created in the constructor, is emulated by being placed 480 // in the light DOM. 481 // 482 // The resulting order is on native is: Clone, Adopt, Upgrade, Process, 483 // Update, Connect. document.importNode() performs Clone, Adopt, and Upgrade 484 // in one step. 485 // 486 // The Custom Elements v1 polyfill supports upgrade(), so the order when 487 // polyfilled is the more ideal: Clone, Process, Adopt, Upgrade, Update, 488 // Connect. 489 const fragment = isCEPolyfill ? 490 this.template.element.content.cloneNode(true) : 491 document.importNode(this.template.element.content, true); 492 const stack = []; 493 const parts = this.template.parts; 494 // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null 495 const walker = document.createTreeWalker(fragment, 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */, null, false); 496 let partIndex = 0; 497 let nodeIndex = 0; 498 let part; 499 let node = walker.nextNode(); 500 // Loop through all the nodes and parts of a template 501 while (partIndex < parts.length) { 502 part = parts[partIndex]; 503 if (!isTemplatePartActive(part)) { 504 this.__parts.push(undefined); 505 partIndex++; 506 continue; 507 } 508 // Progress the tree walker until we find our next part's node. 509 // Note that multiple parts may share the same node (attribute parts 510 // on a single element), so this loop may not run at all. 511 while (nodeIndex < part.index) { 512 nodeIndex++; 513 if (node.nodeName === 'TEMPLATE') { 514 stack.push(node); 515 walker.currentNode = node.content; 516 } 517 if ((node = walker.nextNode()) === null) { 518 // We've exhausted the content inside a nested template element. 519 // Because we still have parts (the outer for-loop), we know: 520 // - There is a template in the stack 521 // - The walker will find a nextNode outside the template 522 walker.currentNode = stack.pop(); 523 node = walker.nextNode(); 524 } 525 } 526 // We've arrived at our part's node. 527 if (part.type === 'node') { 528 const part = this.processor.handleTextExpression(this.options); 529 part.insertAfterNode(node.previousSibling); 530 this.__parts.push(part); 531 } 532 else { 533 this.__parts.push(...this.processor.handleAttributeExpressions(node, part.name, part.strings, this.options)); 534 } 535 partIndex++; 536 } 537 if (isCEPolyfill) { 538 document.adoptNode(fragment); 539 customElements.upgrade(fragment); 540 } 541 return fragment; 542 } 543} 544 545/** 546 * @license 547 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 548 * This code may only be used under the BSD style license found at 549 * http://polymer.github.io/LICENSE.txt 550 * The complete set of authors may be found at 551 * http://polymer.github.io/AUTHORS.txt 552 * The complete set of contributors may be found at 553 * http://polymer.github.io/CONTRIBUTORS.txt 554 * Code distributed by Google as part of the polymer project is also 555 * subject to an additional IP rights grant found at 556 * http://polymer.github.io/PATENTS.txt 557 */ 558/** 559 * Our TrustedTypePolicy for HTML which is declared using the html template 560 * tag function. 561 * 562 * That HTML is a developer-authored constant, and is parsed with innerHTML 563 * before any untrusted expressions have been mixed in. Therefor it is 564 * considered safe by construction. 565 */ 566const policy = window.trustedTypes && 567 trustedTypes.createPolicy('lit-html', { createHTML: (s) => s }); 568const commentMarker = ` ${marker} `; 569/** 570 * The return type of `html`, which holds a Template and the values from 571 * interpolated expressions. 572 */ 573class TemplateResult { 574 constructor(strings, values, type, processor) { 575 this.strings = strings; 576 this.values = values; 577 this.type = type; 578 this.processor = processor; 579 } 580 /** 581 * Returns a string of HTML used to create a `<template>` element. 582 */ 583 getHTML() { 584 const l = this.strings.length - 1; 585 let html = ''; 586 let isCommentBinding = false;
587 for (let i = 0; i < l; i++) { 588 const s = this.strings[i]; 589 // For each binding we want to determine the kind of marker to insert 590 // into the template source before it's parsed by the browser's HTML 591 // parser. The marker type is based on whether the expression is in an 592 // attribute, text, or comment position. 593 // * For node-position bindings we insert a comment with the marker 594 // sentinel as its text content, like <!--{{lit-guid}}-->. 595 // * For attribute bindings we insert just the marker sentinel for the 596 // first binding, so that we support unquoted attribute bindings. 597 // Subsequent bindings can use a comment marker because multi-binding 598 // attributes must be quoted. 599 // * For comment bindings we insert just the marker sentinel so we don't 600 // close the comment. 601 // 602 // The following code scans the template source, but is *not* an HTML 603 // parser. We don't need to track the tree structure of the HTML, only 604 // whether a binding is inside a comment, and if not, if it appears to be 605 // the first binding in an attribute. 606 const commentOpen = s.lastIndexOf('<!--'); 607 // We're in comment position if we have a comment open with no following 608 // comment close. Because <-- can appear in an attribute value there can 609 // be false positives. 610 isCommentBinding = (commentOpen > -1 || isCommentBinding) && 611 s.indexOf('-->', commentOpen + 1) === -1; 612 // Check to see if we have an attribute-like sequence preceding the 613 // expression. This can match "name=value" like structures in text, 614 // comments, and attribute values, so there can be false-positives. 615 const attributeMatch = lastAttributeNameRegex.exec(s); 616 if (attributeMatch === null) { 617 // We're only in this branch if we don't have a attribute-like 618 // preceding sequence. For comments, this guards against unusual 619 // attribute values like <div foo="<!--${'bar'}">. Cases like 620 // <!-- foo=${'bar'}--> are handled correctly in the attribute branch 621 // below. 622 html += s + (isCommentBinding ? commentMarker : nodeMarker); 623 } 624 else { 625 // For attributes we use just a marker sentinel, and also append a 626 // $lit$ suffix to the name to opt-out of attribute-specific parsing 627 // that IE and Edge do for style and certain SVG attributes. 628 html += s.substr(0, attributeMatch.index) + attributeMatch[1] + 629 attributeMatch[2] + boundAttributeSuffix + attributeMatch[3] + 630 marker; 631 } 632 } 633 html += this.strings[l]; 634 return html; 635 } 636 getTemplateElement() { 637 const template = document.createElement('template'); 638 let value = this.getHTML(); 639 if (policy !== undefined) { 640 // this is secure because `this.strings` is a TemplateStringsArray. 641 // TODO: validate this when 642 // https://github.com/tc39/proposal-array-is-template-object is 643 // implemented. 644 value = policy.createHTML(value); 645 } 646 template.innerHTML = value; 647 return template; 648 } 649} 650 651/** 652 * @license 653 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 654 * This code may only be used under the BSD style license found at 655 * http://polymer.github.io/LICENSE.txt 656 * The complete set of authors may be found at 657 * http://polymer.github.io/AUTHORS.txt 658 * The complete set of contributors may be found at 659 * http://polymer.github.io/CONTRIBUTORS.txt 660 * Code distributed by Google as part of the polymer project is also 661 * subject to an additional IP rights grant found at 662 * http://polymer.github.io/PATENTS.txt 663 */ 664const isPrimitive = (value) => { 665 return (value === null || 666 !(typeof value === 'object' || typeof value === 'function')); 667}; 668const isIterable = (value) => { 669 return Array.isArray(value) || 670 // eslint-disable-next-line @typescript-eslint/no-explicit-any 671 !!(value && value[Symbol.iterator]); 672}; 673/** 674 * Writes attribute values to the DOM for a group of AttributeParts bound to a 675 * single attribute. The value is only set once even if there are multiple parts 676 * for an attribute. 677 */ 678class AttributeCommitter { 679 constructor(element, name, strings) { 680 this.dirty = true; 681 this.element = element; 682 this.name = name; 683 this.strings = strings; 684 this.parts = []; 685 for (let i = 0; i < strings.length - 1; i++) { 686 this.parts[i] = this._createPart(); 687 } 688 } 689 /** 690 * Creates a single part. Override this to create a differnt type of part. 691 */ 692 _createPart() { 693 return new AttributePart(this); 694 } 695 _getValue() { 696 const strings = this.strings; 697 const l = strings.length - 1; 698 const parts = this.parts; 699 // If we're assigning an attribute via syntax like: 700 // attr="${foo}" or attr=${foo} 701 // but not 702 // attr="${foo} ${bar}" or attr="${foo} baz" 703 // then we don't want to coerce the attribute value into one long 704 // string. Instead we want to just return the value itself directly, 705 // so that sanitizeDOMValue can get the actual value rather than 706 // String(value) 707 // The exception is if v is an array, in which case we do want to smash 708 // it together into a string without calling String() on the array. 709 //
710 // This also allows trusted values (when using TrustedTypes) being 711 // assigned to DOM sinks without being stringified in the process. 712 if (l === 1 && strings[0] === '' && strings[1] === '') { 713 const v = parts[0].value; 714 if (typeof v === 'symbol') { 715 return String(v); 716 } 717 if (typeof v === 'string' || !isIterable(v)) { 718 return v; 719 } 720 } 721 let text = ''; 722 for (let i = 0; i < l; i++) { 723 text += strings[i]; 724 const part = parts[i]; 725 if (part !== undefined) { 726 const v = part.value; 727 if (isPrimitive(v) || !isIterable(v)) { 728 text += typeof v === 'string' ? v : String(v); 729 } 730 else { 731 for (const t of v) { 732 text += typeof t === 'string' ? t : String(t); 733 } 734 } 735 } 736 } 737 text += strings[l]; 738 return text; 739 } 740 commit() { 741 if (this.dirty) { 742 this.dirty = false; 743 this.element.setAttribute(this.name, this._getValue()); 744 } 745 } 746} 747/** 748 * A Part that controls all or part of an attribute value. 749 */ 750class AttributePart { 751 constructor(committer) { 752 this.value = undefined; 753 this.committer = committer; 754 } 755 setValue(value) { 756 if (value !== noChange && (!isPrimitive(value) || value !== this.value)) { 757 this.value = value; 758 // If the value is a not a directive, dirty the committer so that it'll 759 // call setAttribute. If the value is a directive, it'll dirty the 760 // committer if it calls setValue(). 761 if (!isDirective(value)) { 762 this.committer.dirty = true; 763 } 764 } 765 } 766 commit() { 767 while (isDirective(this.value)) { 768 const directive = this.value; 769 this.value = noChange; 770 directive(this); 771 } 772 if (this.value === noChange) { 773 return; 774 } 775 this.committer.commit(); 776 } 777} 778/** 779 * A Part that controls a location within a Node tree. Like a Range, NodePart 780 * has start and end locations and can set and update the Nodes between those 781 * locations. 782 * 783 * NodeParts support several value types: primitives, Nodes, TemplateResults, 784 * as well as arrays and iterables of those types. 785 */ 786class NodePart { 787 constructor(options) { 788 this.value = undefined; 789 this.__pendingValue = undefined; 790 this.options = options; 791 } 792 /** 793 * Appends this part into a container. 794 * 795 * This part must be empty, as its contents are not automatically moved. 796 */ 797 appendInto(container) { 798 this.startNode = container.appendChild(createMarker()); 799 this.endNode = container.appendChild(createMarker()); 800 } 801 /** 802 * Inserts this part after the `ref` node (between `ref` and `ref`'s next 803 * sibling). Both `ref` and its next sibling must be static, unchanging nodes 804 * such as those that appear in a literal section of a template. 805 * 806 * This part must be empty, as its contents are not automatically moved. 807 */ 808 insertAfterNode(ref) { 809 this.startNode = ref; 810 this.endNode = ref.nextSibling; 811 } 812 /** 813 * Appends this part into a parent part. 814 * 815 * This part must be empty, as its contents are not automatically moved. 816 */ 817 appendIntoPart(part) { 818 part.__insert(this.startNode = createMarker()); 819 part.__insert(this.endNode = createMarker()); 820 } 821 /** 822 * Inserts this part after the `ref` part. 823 * 824 * This part must be empty, as its contents are not automatically moved. 825 */ 826 insertAfterPart(ref) { 827 ref.__insert(this.startNode = createMarker()); 828 this.endNode = ref.endNode; 829 ref.endNode = this.startNode;
vendor: 7,378 bytes, lines 830-1033
830 } 831 setValue(value) { 832 this.__pendingValue = value; 833 } 834 commit() { 835 if (this.startNode.parentNode === null) { 836 return; 837 } 838 while (isDirective(this.__pendingValue)) { 839 const directive = this.__pendingValue; 840 this.__pendingValue = noChange; 841 directive(this); 842 } 843 const value = this.__pendingValue; 844 if (value === noChange) { 845 return; 846 } 847 if (isPrimitive(value)) { 848 if (value !== this.value) { 849 this.__commitText(value); 850 } 851 } 852 else if (value instanceof TemplateResult) { 853 this.__commitTemplateResult(value); 854 } 855 else if (value instanceof Node) { 856 this.__commitNode(value); 857 } 858 else if (isIterable(value)) { 859 this.__commitIterable(value); 860 } 861 else if (value === nothing) { 862 this.value = nothing; 863 this.clear(); 864 } 865 else { 866 // Fallback, will render the string representation 867 this.__commitText(value); 868 } 869 } 870 __insert(node) { 871 this.endNode.parentNode.insertBefore(node, this.endNode); 872 } 873 __commitNode(value) { 874 if (this.value === value) { 875 return; 876 } 877 this.clear(); 878 this.__insert(value); 879 this.value = value; 880 } 881 __commitText(value) { 882 const node = this.startNode.nextSibling; 883 value = value == null ? '' : value; 884 // If `value` isn't already a string, we explicitly convert it here in case 885 // it can't be implicitly converted - i.e. it's a symbol. 886 const valueAsString = typeof value === 'string' ? value : String(value); 887 if (node === this.endNode.previousSibling && 888 node.nodeType === 3 /* Node.TEXT_NODE */) { 889 // If we only have a single text node between the markers, we can just 890 // set its value, rather than replacing it. 891 // TODO(justinfagnani): Can we just check if this.value is primitive? 892 node.data = valueAsString; 893 } 894 else { 895 this.__commitNode(document.createTextNode(valueAsString)); 896 } 897 this.value = value; 898 } 899 __commitTemplateResult(value) { 900 const template = this.options.templateFactory(value); 901 if (this.value instanceof TemplateInstance && 902 this.value.template === template) { 903 this.value.update(value.values); 904 } 905 else { 906 // Make sure we propagate the template processor from the TemplateResult 907 // so that we use its syntax extension, etc. The template factory comes 908 // from the render function options so that it can control template 909 // caching and preprocessing. 910 const instance = new TemplateInstance(template, value.processor, this.options); 911 const fragment = instance._clone(); 912 instance.update(value.values); 913 this.__commitNode(fragment); 914 this.value = instance; 915 } 916 } 917 __commitIterable(value) { 918 // For an Iterable, we create a new InstancePart per item, then set its 919 // value to the item. This is a little bit of overhead for every item in 920 // an Iterable, but it lets us recurse easily and efficiently update Arrays 921 // of TemplateResults that will be commonly returned from expressions like: 922 // array.map((i) => html`${i}`), by reusing existing TemplateInstances. 923 // If _value is an array, then the previous render was of an 924 // iterable and _value will contain the NodeParts from the previous 925 // render. If _value is not an array, clear this part and make a new 926 // array for NodeParts. 927 if (!Array.isArray(this.value)) { 928 this.value = []; 929 this.clear(); 930 } 931 // Lets us keep track of how many items we stamped so we can clear leftover 932 // items from a previous render 933 const itemParts = this.value; 934 let partIndex = 0; 935 let itemPart; 936 for (const item of value) { 937 // Try to reuse an existing part 938 itemPart = itemParts[partIndex]; 939 // If no existing part, create a new one 940 if (itemPart === undefined) { 941 itemPart = new NodePart(this.options); 942 itemParts.push(itemPart); 943 if (partIndex === 0) { 944 itemPart.appendIntoPart(this); 945 } 946 else { 947 itemPart.insertAfterPart(itemParts[partIndex - 1]); 948 } 949 } 950 itemPart.setValue(item); 951 itemPart.commit(); 952 partIndex++; 953 } 954 if (partIndex < itemParts.length) { 955 // Truncate the parts array so _value reflects the current state 956 itemParts.length = partIndex; 957 this.clear(itemPart && itemPart.endNode); 958 } 959 } 960 clear(startNode = this.startNode) { 961 removeNodes(this.startNode.parentNode, startNode.nextSibling, this.endNode); 962 } 963} 964/** 965 * Implements a boolean attribute, roughly as defined in the HTML 966 * specification. 967 * 968 * If the value is truthy, then the attribute is present with a value of 969 * ''. If the value is falsey, the attribute is removed. 970 */ 971class BooleanAttributePart { 972 constructor(element, name, strings) { 973 this.value = undefined; 974 this.__pendingValue = undefined; 975 if (strings.length !== 2 || strings[0] !== '' || strings[1] !== '') { 976 throw new Error('Boolean attributes can only contain a single expression'); 977 } 978 this.element = element; 979 this.name = name; 980 this.strings = strings; 981 } 982 setValue(value) { 983 this.__pendingValue = value; 984 } 985 commit() { 986 while (isDirective(this.__pendingValue)) { 987 const directive = this.__pendingValue; 988 this.__pendingValue = noChange; 989 directive(this); 990 } 991 if (this.__pendingValue === noChange) { 992 return; 993 } 994 const value = !!this.__pendingValue; 995 if (this.value !== value) { 996 if (value) { 997 this.element.setAttribute(this.name, ''); 998 } 999 else { 1000 this.element.removeAttribute(this.name); 1001 } 1002 this.value = value; 1003 } 1004 this.__pendingValue = noChange; 1005 } 1006} 1007/** 1008 * Sets attribute values for PropertyParts, so that the value is only set once 1009 * even if there are multiple parts for a property. 1010 * 1011 * If an expression controls the whole property value, then the value is simply 1012 * assigned to the property under control. If there are string literals or 1013 * multiple expressions, then the strings are expressions are interpolated into 1014 * a string first. 1015 */ 1016class PropertyCommitter extends AttributeCommitter { 1017 constructor(element, name, strings) { 1018 super(element, name, strings); 1019 this.single = 1020 (strings.length === 2 && strings[0] === '' && strings[1] === ''); 1021 } 1022 _createPart() { 1023 return new PropertyPart(this); 1024 } 1025 _getValue() { 1026 if (this.single) { 1027 return this.parts[0].value; 1028 } 1029 return super._getValue(); 1030 } 1031 commit() { 1032 if (this.dirty) { 1033 this.dirty = false;
1034 // eslint-disable-next-line @typescript-eslint/no-explicit-any 1035 this.element[this.name] = this._getValue(); 1036 } 1037 } 1038} 1039class PropertyPart extends AttributePart { 1040} 1041// Detect event listener options support. If the `capture` property is read 1042// from the options object, then options are supported. If not, then the third 1043// argument to add/removeEventListener is interpreted as the boolean capture 1044// value so we should only pass the `capture` property. 1045let eventOptionsSupported = false; 1046// Wrap into an IIFE because MS Edge <= v41 does not support having try/catch 1047// blocks right into the body of a module 1048(() => { 1049 try { 1050 const options = { 1051 get capture() { 1052 eventOptionsSupported = true; 1053 return false; 1054 } 1055 }; 1056 // eslint-disable-next-line @typescript-eslint/no-explicit-any 1057 window.addEventListener('test', options, options); 1058 // eslint-disable-next-line @typescript-eslint/no-explicit-any 1059 window.removeEventListener('test', options, options); 1060 } 1061 catch (_e) { 1062 // event options not supported 1063 } 1064})(); 1065class EventPart { 1066 constructor(element, eventName, eventContext) { 1067 this.value = undefined; 1068 this.__pendingValue = undefined; 1069 this.element = element; 1070 this.eventName = eventName; 1071 this.eventContext = eventContext; 1072 this.__boundHandleEvent = (e) => this.handleEvent(e); 1073 } 1074 setValue(value) { 1075 this.__pendingValue = value; 1076 } 1077 commit() { 1078 while (isDirective(this.__pendingValue)) { 1079 const directive = this.__pendingValue; 1080 this.__pendingValue = noChange; 1081 directive(this); 1082 } 1083 if (this.__pendingValue === noChange) { 1084 return; 1085 } 1086 const newListener = this.__pendingValue; 1087 const oldListener = this.value; 1088 const shouldRemoveListener = newListener == null || 1089 oldListener != null && 1090 (newListener.capture !== oldListener.capture || 1091 newListener.once !== oldListener.once || 1092 newListener.passive !== oldListener.passive); 1093 const shouldAddListener = newListener != null && (oldListener == null || shouldRemoveListener); 1094 if (shouldRemoveListener) { 1095 this.element.removeEventListener(this.eventName, this.__boundHandleEvent, this.__options); 1096 } 1097 if (shouldAddListener) { 1098 this.__options = getOptions(newListener); 1099 this.element.addEventListener(this.eventName, this.__boundHandleEvent, this.__options); 1100 } 1101 this.value = newListener; 1102 this.__pendingValue = noChange; 1103 } 1104 handleEvent(event) { 1105 if (typeof this.value === 'function') { 1106 this.value.call(this.eventContext || this.element, event); 1107 } 1108 else { 1109 this.value.handleEvent(event); 1110 } 1111 } 1112} 1113// We copy options because of the inconsistent behavior of browsers when reading 1114// the third argument of add/removeEventListener. IE11 doesn't support options 1115// at all. Chrome 41 only reads `capture` if the argument is an object. 1116const getOptions = (o) => o && 1117 (eventOptionsSupported ? 1118 { capture: o.capture, passive: o.passive, once: o.once } : 1119 o.capture); 1120 1121/** 1122 * @license 1123 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 1124 * This code may only be used under the BSD style license found at 1125 * http://polymer.github.io/LICENSE.txt 1126 * The complete set of authors may be found at 1127 * http://polymer.github.io/AUTHORS.txt 1128 * The complete set of contributors may be found at 1129 * http://polymer.github.io/CONTRIBUTORS.txt 1130 * Code distributed by Google as part of the polymer project is also 1131 * subject to an additional IP rights grant found at 1132 * http://polymer.github.io/PATENTS.txt 1133 */ 1134/** 1135 * The default TemplateFactory which caches Templates keyed on 1136 * result.type and result.strings. 1137 */ 1138function templateFactory(result) { 1139 let templateCache = templateCaches.get(result.type); 1140 if (templateCache === undefined) { 1141 templateCache = {
1142 stringsArray: new WeakMap(), 1143 keyString: new Map() 1144 }; 1145 templateCaches.set(result.type, templateCache); 1146 } 1147 let template = templateCache.stringsArray.get(result.strings); 1148 if (template !== undefined) { 1149 return template; 1150 } 1151 // If the TemplateStringsArray is new, generate a key from the strings 1152 // This key is shared between all templates with identical content 1153 const key = result.strings.join(marker); 1154 // Check if we already have a Template for this key 1155 template = templateCache.keyString.get(key); 1156 if (template === undefined) { 1157 // If we have not seen this key before, create a new Template 1158 template = new Template(result, result.getTemplateElement()); 1159 // Cache the Template for this key 1160 templateCache.keyString.set(key, template); 1161 } 1162 // Cache all future queries for this TemplateStringsArray 1163 templateCache.stringsArray.set(result.strings, template); 1164 return template; 1165} 1166const templateCaches = new Map(); 1167 1168/** 1169 * @license 1170 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 1171 * This code may only be used under the BSD style license found at 1172 * http://polymer.github.io/LICENSE.txt 1173 * The complete set of authors may be found at 1174 * http://polymer.github.io/AUTHORS.txt 1175 * The complete set of contributors may be found at 1176 * http://polymer.github.io/CONTRIBUTORS.txt 1177 * Code distributed by Google as part of the polymer project is also 1178 * subject to an additional IP rights grant found at 1179 * http://polymer.github.io/PATENTS.txt 1180 */ 1181const parts = new WeakMap(); 1182/** 1183 * Renders a template result or other value to a container. 1184 * 1185 * To update a container with new values, reevaluate the template literal and 1186 * call `render` with the new result. 1187 * 1188 * @param result Any value renderable by NodePart - typically a TemplateResult 1189 * created by evaluating a template tag like `html` or `svg`. 1190 * @param container A DOM parent to render to. The entire contents are either 1191 * replaced, or efficiently updated if the same result type was previous 1192 * rendered there. 1193 * @param options RenderOptions for the entire render tree rendered to this 1194 * container. Render options must *not* change between renders to the same 1195 * container, as those changes will not effect previously rendered DOM. 1196 */ 1197const render = (result, container, options) => { 1198 let part = parts.get(container); 1199 if (part === undefined) { 1200 removeNodes(container, container.firstChild); 1201 parts.set(container, part = new NodePart(Object.assign({ templateFactory }, options))); 1202 part.appendInto(container); 1203 } 1204 part.setValue(result); 1205 part.commit(); 1206}; 1207 1208/** 1209 * @license 1210 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 1211 * This code may only be used under the BSD style license found at 1212 * http://polymer.github.io/LICENSE.txt 1213 * The complete set of authors may be found at 1214 * http://polymer.github.io/AUTHORS.txt 1215 * The complete set of contributors may be found at 1216 * http://polymer.github.io/CONTRIBUTORS.txt 1217 * Code distributed by Google as part of the polymer project is also 1218 * subject to an additional IP rights grant found at 1219 * http://polymer.github.io/PATENTS.txt 1220 */ 1221/** 1222 * Creates Parts when a template is instantiated. 1223 */ 1224class DefaultTemplateProcessor { 1225 /** 1226 * Create parts for an attribute-position binding, given the event, attribute 1227 * name, and string literals. 1228 * 1229 * @param element The element containing the binding 1230 * @param name The attribute name 1231 * @param strings The string literals. There are always at least two strings, 1232 * event for fully-controlled bindings with a single expression. 1233 */ 1234 handleAttributeExpressions(element, name, strings, options) { 1235 const prefix = name[0]; 1236 if (prefix === '.') { 1237 const committer = new PropertyCommitter(element, name.slice(1), strings); 1238 return committer.parts; 1239 } 1240 if (prefix === '@') { 1241 return [new EventPart(element, name.slice(1), options.eventContext)]; 1242 } 1243 if (prefix === '?') { 1244 return [new BooleanAttributePart(element, name.slice(1), strings)]; 1245 } 1246 const committer = new AttributeCommitter(element, name, strings); 1247 return committer.parts; 1248 } 1249 /** 1250 * Create parts for a text-position binding. 1251 * @param templateFactory 1252 */ 1253 handleTextExpression(options) { 1254 return new NodePart(options); 1255 } 1256} 1257const defaultTemplateProcessor = new DefaultTemplateProcessor(); 1258 1259/** 1260 * @license 1261 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 1262 * This code may only be used under the BSD style license found at 1263 * http://polymer.github.io/LICENSE.txt 1264 * The complete set of authors may be found at 1265 * http://polymer.github.io/AUTHORS.txt 1266 * The complete set of contributors may be found at 1267 * http://polymer.github.io/CONTRIBUTORS.txt 1268 * Code distributed by Google as part of the polymer project is also 1269 * subject to an additional IP rights grant found at 1270 * http://polymer.github.io/PATENTS.txt 1271 */ 1272// IMPORTANT: do not change the property name or the assignment expression.
1273// This line will be used in regexes to search for lit-html usage. 1274// TODO(justinfagnani): inject version number at build time 1275if (typeof window !== 'undefined') { 1276 (window['litHtmlVersions'] || (window['litHtmlVersions'] = [])).push('1.3.0'); 1277} 1278/** 1279 * Interprets a template literal as an HTML template that can efficiently 1280 * render to and update a container. 1281 */ 1282const html = (strings, ...values) => new TemplateResult(strings, values, 'html', defaultTemplateProcessor); 1283 1284/** 1285 * @license 1286 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 1287 * This code may only be used under the BSD style license found at 1288 * http://polymer.github.io/LICENSE.txt 1289 * The complete set of authors may be found at 1290 * http://polymer.github.io/AUTHORS.txt 1291 * The complete set of contributors may be found at 1292 * http://polymer.github.io/CONTRIBUTORS.txt 1293 * Code distributed by Google as part of the polymer project is also 1294 * subject to an additional IP rights grant found at 1295 * http://polymer.github.io/PATENTS.txt 1296 */ 1297// Get a key to lookup in `templateCaches`. 1298const getTemplateCacheKey = (type, scopeName) => `${type}--${scopeName}`; 1299let compatibleShadyCSSVersion = true; 1300if (typeof window.ShadyCSS === 'undefined') { 1301 compatibleShadyCSSVersion = false; 1302} 1303else if (typeof window.ShadyCSS.prepareTemplateDom === 'undefined') { 1304 console.warn(`Incompatible ShadyCSS version detected. ` + 1305 `Please update to at least @webcomponents/[email protected] and ` + 1306 `@webcomponents/[email protected].`); 1307 compatibleShadyCSSVersion = false; 1308} 1309/** 1310 * Template factory which scopes template DOM using ShadyCSS. 1311 * @param scopeName {string} 1312 */ 1313const shadyTemplateFactory = (scopeName) => (result) => { 1314 const cacheKey = getTemplateCacheKey(result.type, scopeName); 1315 let templateCache = templateCaches.get(cacheKey); 1316 if (templateCache === undefined) { 1317 templateCache = { 1318 stringsArray: new WeakMap(), 1319 keyString: new Map() 1320 }; 1321 templateCaches.set(cacheKey, templateCache); 1322 } 1323 let template = templateCache.stringsArray.get(result.strings); 1324 if (template !== undefined) { 1325 return template; 1326 } 1327 const key = result.strings.join(marker); 1328 template = templateCache.keyString.get(key); 1329 if (template === undefined) { 1330 const element = result.getTemplateElement(); 1331 if (compatibleShadyCSSVersion) { 1332 window.ShadyCSS.prepareTemplateDom(element, scopeName); 1333 } 1334 template = new Template(result, element); 1335 templateCache.keyString.set(key, template); 1336 } 1337 templateCache.stringsArray.set(result.strings, template); 1338 return template; 1339}; 1340const TEMPLATE_TYPES = ['html', 'svg']; 1341/** 1342 * Removes all style elements from Templates for the given scopeName. 1343 */ 1344const removeStylesFromLitTemplates = (scopeName) => { 1345 TEMPLATE_TYPES.forEach((type) => { 1346 const templates = templateCaches.get(getTemplateCacheKey(type, scopeName)); 1347 if (templates !== undefined) { 1348 templates.keyString.forEach((template) => { 1349 const { element: { content } } = template; 1350 // IE 11 doesn't support the iterable param Set constructor 1351 const styles = new Set(); 1352 Array.from(content.querySelectorAll('style')).forEach((s) => { 1353 styles.add(s); 1354 }); 1355 removeNodesFromTemplate(template, styles); 1356 }); 1357 } 1358 }); 1359}; 1360const shadyRenderSet = new Set(); 1361/** 1362 * For the given scope name, ensures that ShadyCSS style scoping is performed. 1363 * This is done just once per scope name so the fragment and template cannot 1364 * be modified. 1365 * (1) extracts styles from the rendered fragment and hands them to ShadyCSS 1366 * to be scoped and appended to the document 1367 * (2) removes style elements from all lit-html Templates for this scope name. 1368 * 1369 * Note, <style> elements can only be placed into templates for the 1370 * initial rendering of the scope. If <style> elements are included in templates 1371 * dynamically rendered to the scope (after the first scope render), they will 1372 * not be scoped and the <style> will be left in the template and rendered 1373 * output. 1374 */ 1375const prepareTemplateStyles = (scopeName, renderedDOM, template) => { 1376 shadyRenderSet.add(scopeName); 1377 // If `renderedDOM` is stamped from a Template, then we need to edit that 1378 // Template's underlying template element. Otherwise, we create one here 1379 // to give to ShadyCSS, which still requires one while scoping. 1380 const templateElement = !!template ? template.element : document.createElement('template'); 1381 // Move styles out of rendered DOM and store. 1382 const styles = renderedDOM.querySelectorAll('style'); 1383 const { length } = styles; 1384 // If there are no styles, skip unnecessary work 1385 if (length === 0) { 1386 // Ensure prepareTemplateStyles is called to support adding 1387 // styles via `prepareAdoptedCssText` since that requires that 1388 // `prepareTemplateStyles` is called. 1389 // 1390 // ShadyCSS will only update styles containing @apply in the template 1391 // given to `prepareTemplateStyles`. If no lit Template was given, 1392 // ShadyCSS will not be able to update uses of @apply in any relevant 1393 // template. However, this is not a problem because we only create the 1394 // template for the purpose of supporting `prepareAdoptedCssText`, 1395 // which doesn't support @apply at all. 1396 window.ShadyCSS.prepareTemplateStyles(templateElement, scopeName); 1397 return; 1398 } 1399 const condensedStyle = document.createElement('style'); 1400 // Collect styles into a single style. This helps us make sure ShadyCSS 1401 // manipulations will not prevent us from being able to fix up template 1402 // part indices. 1403 // NOTE: collecting styles is inefficient for browsers but ShadyCSS 1404 // currently does this anyway. When it does not, this should be changed. 1405 for (let i = 0; i < length; i++) { 1406 const style = styles[i]; 1407 style.parentNode.removeChild(style); 1408 condensedStyle.textContent += style.textContent; 1409 } 1410 // Remove styles from nested templates in this scope. 1411 removeStylesFromLitTemplates(scopeName); 1412 // And then put the condensed style into the "root" template passed in as 1413 // `template`. 1414 const content = templateElement.content; 1415 if (!!template) { 1416 insertNodeIntoTemplate(template, condensedStyle, content.firstChild); 1417 } 1418 else { 1419 content.insertBefore(condensedStyle, content.firstChild); 1420 } 1421 // Note, it's important that ShadyCSS gets the template that `lit-html` 1422 // will actually render so that it can update the style inside when 1423 // needed (e.g. @apply native Shadow DOM case). 1424 window.ShadyCSS.prepareTemplateStyles(templateElement, scopeName); 1425 const style = content.querySelector('style'); 1426 if (window.ShadyCSS.nativeShadow && style !== null) { 1427 // When in native Shadow DOM, ensure the style created by ShadyCSS is 1428 // included in initially rendered output (`renderedDOM`). 1429 renderedDOM.insertBefore(style.cloneNode(true), renderedDOM.firstChild); 1430 } 1431 else if (!!template) { 1432 // When no style is left in the template, parts will be broken as a 1433 // result. To fix this, we put back the style node ShadyCSS removed 1434 // and then tell lit to remove that node from the template. 1435 // There can be no style in the template in 2 cases (1) when Shady DOM 1436 // is in use, ShadyCSS removes all styles, (2) when native Shadow DOM
1437 // is in use ShadyCSS removes the style if it contains no content. 1438 // NOTE, ShadyCSS creates its own style so we can safely add/remove 1439 // `condensedStyle` here. 1440 content.insertBefore(condensedStyle, content.firstChild); 1441 const removes = new Set(); 1442 removes.add(condensedStyle); 1443 removeNodesFromTemplate(template, removes); 1444 } 1445}; 1446/** 1447 * Extension to the standard `render` method which supports rendering 1448 * to ShadowRoots when the ShadyDOM (https://github.com/webcomponents/shadydom) 1449 * and ShadyCSS (https://github.com/webcomponents/shadycss) polyfills are used 1450 * or when the webcomponentsjs 1451 * (https://github.com/webcomponents/webcomponentsjs) polyfill is used. 1452 * 1453 * Adds a `scopeName` option which is used to scope element DOM and stylesheets 1454 * when native ShadowDOM is unavailable. The `scopeName` will be added to 1455 * the class attribute of all rendered DOM. In addition, any style elements will 1456 * be automatically re-written with this `scopeName` selector and moved out 1457 * of the rendered DOM and into the document `<head>`. 1458 * 1459 * It is common to use this render method in conjunction with a custom element 1460 * which renders a shadowRoot. When this is done, typically the element's 1461 * `localName` should be used as the `scopeName`. 1462 * 1463 * In addition to DOM scoping, ShadyCSS also supports a basic shim for css 1464 * custom properties (needed only on older browsers like IE11) and a shim for 1465 * a deprecated feature called `@apply` that supports applying a set of css 1466 * custom properties to a given location. 1467 * 1468 * Usage considerations: 1469 * 1470 * * Part values in `<style>` elements are only applied the first time a given 1471 * `scopeName` renders. Subsequent changes to parts in style elements will have 1472 * no effect. Because of this, parts in style elements should only be used for 1473 * values that will never change, for example parts that set scope-wide theme 1474 * values or parts which render shared style elements. 1475 * 1476 * * Note, due to a limitation of the ShadyDOM polyfill, rendering in a 1477 * custom element's `constructor` is not supported. Instead rendering should 1478 * either done asynchronously, for example at microtask timing (for example 1479 * `Promise.resolve()`), or be deferred until the first time the element's 1480 * `connectedCallback` runs. 1481 * 1482 * Usage considerations when using shimmed custom properties or `@apply`: 1483 * 1484 * * Whenever any dynamic changes are made which affect 1485 * css custom properties, `ShadyCSS.styleElement(element)` must be called 1486 * to update the element. There are two cases when this is needed: 1487 * (1) the element is connected to a new parent, (2) a class is added to the 1488 * element that causes it to match different custom properties. 1489 * To address the first case when rendering a custom element, `styleElement` 1490 * should be called in the element's `connectedCallback`. 1491 * 1492 * * Shimmed custom properties may only be defined either for an entire 1493 * shadowRoot (for example, in a `:host` rule) or via a rule that directly 1494 * matches an element with a shadowRoot. In other words, instead of flowing from 1495 * parent to child as do native css custom properties, shimmed custom properties 1496 * flow only from shadowRoots to nested shadowRoots. 1497 * 1498 * * When using `@apply` mixing css shorthand property names with 1499 * non-shorthand names (for example `border` and `border-width`) is not 1500 * supported. 1501 */ 1502const render$1 = (result, container, options) => { 1503 if (!options || typeof options !== 'object' || !options.scopeName) { 1504 throw new Error('The `scopeName` option is required.'); 1505 } 1506 const scopeName = options.scopeName; 1507 const hasRendered = parts.has(container); 1508 const needsScoping = compatibleShadyCSSVersion && 1509 container.nodeType === 11 /* Node.DOCUMENT_FRAGMENT_NODE */ && 1510 !!container.host; 1511 // Handle first render to a scope specially... 1512 const firstScopeRender = needsScoping && !shadyRenderSet.has(scopeName); 1513 // On first scope render, render into a fragment; this cannot be a single 1514 // fragment that is reused since nested renders can occur synchronously. 1515 const renderContainer = firstScopeRender ? document.createDocumentFragment() : container; 1516 render(result, renderContainer, Object.assign({ templateFactory: shadyTemplateFactory(scopeName) }, options)); 1517 // When performing first scope render, 1518 // (1) We've rendered into a fragment so that there's a chance to 1519 // `prepareTemplateStyles` before sub-elements hit the DOM 1520 // (which might cause them to render based on a common pattern of 1521 // rendering in a custom element's `connectedCallback`); 1522 // (2) Scope the template with ShadyCSS one time only for this scope. 1523 // (3) Render the fragment into the container and make sure the 1524 // container knows its `part` is the one we just rendered. This ensures 1525 // DOM will be re-used on subsequent renders. 1526 if (firstScopeRender) { 1527 const part = parts.get(renderContainer); 1528 parts.delete(renderContainer); 1529 // ShadyCSS might have style sheets (e.g. from `prepareAdoptedCssText`) 1530 // that should apply to `renderContainer` even if the rendered value is 1531 // not a TemplateInstance. However, it will only insert scoped styles 1532 // into the document if `prepareTemplateStyles` has already been called 1533 // for the given scope name. 1534 const template = part.value instanceof TemplateInstance ? 1535 part.value.template : 1536 undefined; 1537 prepareTemplateStyles(scopeName, renderContainer, template); 1538 removeNodes(container, container.firstChild); 1539 container.appendChild(renderContainer); 1540 parts.set(container, part); 1541 } 1542 // After elements have hit the DOM, update styling if this is the 1543 // initial render to this container. 1544 // This is needed whenever dynamic changes are made so it would be 1545 // safest to do every render; however, this would regress performance 1546 // so we leave it up to the user to call `ShadyCSS.styleElement` 1547 // for dynamic changes. 1548 if (!hasRendered && needsScoping) { 1549 window.ShadyCSS.styleElement(container.host); 1550 } 1551}; 1552 1553/** 1554 * @license 1555 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 1556 * This code may only be used under the BSD style license found at 1557 * http://polymer.github.io/LICENSE.txt 1558 * The complete set of authors may be found at 1559 * http://polymer.github.io/AUTHORS.txt 1560 * The complete set of contributors may be found at 1561 * http://polymer.github.io/CONTRIBUTORS.txt 1562 * Code distributed by Google as part of the polymer project is also 1563 * subject to an additional IP rights grant found at 1564 * http://polymer.github.io/PATENTS.txt 1565 */ 1566var _a; 1567/** 1568 * Use this module if you want to create your own base class extending 1569 * [[UpdatingElement]]. 1570 * @packageDocumentation 1571 */ 1572/* 1573 * When using Closure Compiler, JSCompiler_renameProperty(property, object) is 1574 * replaced at compile time by the munged name for object[property]. We cannot 1575 * alias this function, so we have to use a small shim that has the same 1576 * behavior when not compiling. 1577 */ 1578window.JSCompiler_renameProperty = 1579 (prop, _obj) => prop; 1580const defaultConverter = { 1581 toAttribute(value, type) { 1582 switch (type) { 1583 case Boolean: 1584 return value ? '' : null; 1585 case Object: 1586 case Array: 1587 // if the value is `null` or `undefined` pass this through 1588 // to allow removing/no change behavior. 1589 return value == null ? value : JSON.stringify(value); 1590 } 1591 return value; 1592 }, 1593 fromAttribute(value, type) { 1594 switch (type) { 1595 case Boolean: 1596 return value !== null; 1597 case Number: 1598 return value === null ? null : Number(value); 1599 case Object: 1600 case Array: 1601 return JSON.parse(value); 1602 } 1603 return value; 1604 } 1605}; 1606/** 1607 * Change function that returns true if `value` is different from `oldValue`. 1608 * This method is used as the default for a property's `hasChanged` function. 1609 */ 1610const notEqual = (value, old) => { 1611 // This ensures (old==NaN, value==NaN) always returns false 1612 return old !== value && (old === old || value === value); 1613}; 1614const defaultPropertyDeclaration = { 1615 attribute: true, 1616 type: String, 1617 converter: defaultConverter, 1618 reflect: false, 1619 hasChanged: notEqual 1620}; 1621const STATE_HAS_UPDATED = 1; 1622const STATE_UPDATE_REQUESTED = 1 << 2; 1623const STATE_IS_REFLECTING_TO_ATTRIBUTE = 1 << 3; 1624const STATE_IS_REFLECTING_TO_PROPERTY = 1 << 4; 1625/** 1626 * The Closure JS Compiler doesn't currently have good support for static 1627 * property semantics where "this" is dynamic (e.g. 1628 * https://github.com/google/closure-compiler/issues/3177 and others) so we use 1629 * this hack to bypass any rewriting by the compiler. 1630 */ 1631const finalized = 'finalized'; 1632/** 1633 * Base element class which manages element properties and attributes. When 1634 * properties change, the `update` method is asynchronously called. This method 1635 * should be supplied by subclassers to render updates as desired. 1636 * @noInheritDoc 1637 */ 1638class UpdatingElement extends HTMLElement { 1639 constructor() { 1640 super(); 1641 this.initialize(); 1642 } 1643 /** 1644 * Returns a list of attributes corresponding to the registered properties. 1645 * @nocollapse 1646 */ 1647 static get observedAttributes() { 1648 // note: piggy backing on this to ensure we're finalized. 1649 this.finalize(); 1650 const attributes = []; 1651 // Use forEach so this works even if for/of loops are compiled to for loops 1652 // expecting arrays
1653 this._classProperties.forEach((v, p) => { 1654 const attr = this._attributeNameForProperty(p, v); 1655 if (attr !== undefined) { 1656 this._attributeToPropertyMap.set(attr, p); 1657 attributes.push(attr); 1658 } 1659 }); 1660 return attributes; 1661 } 1662 /** 1663 * Ensures the private `_classProperties` property metadata is created. 1664 * In addition to `finalize` this is also called in `createProperty` to 1665 * ensure the `@property` decorator can add property metadata. 1666 */ 1667 /** @nocollapse */ 1668 static _ensureClassProperties() { 1669 // ensure private storage for property declarations. 1670 if (!this.hasOwnProperty(JSCompiler_renameProperty('_classProperties', this))) { 1671 this._classProperties = new Map(); 1672 // NOTE: Workaround IE11 not supporting Map constructor argument. 1673 const superProperties = Object.getPrototypeOf(this)._classProperties; 1674 if (superProperties !== undefined) { 1675 superProperties.forEach((v, k) => this._classProperties.set(k, v)); 1676 } 1677 } 1678 } 1679 /** 1680 * Creates a property accessor on the element prototype if one does not exist 1681 * and stores a PropertyDeclaration for the property with the given options. 1682 * The property setter calls the property's `hasChanged` property option 1683 * or uses a strict identity check to determine whether or not to request 1684 * an update. 1685 * 1686 * This method may be overridden to customize properties; however, 1687 * when doing so, it's important to call `super.createProperty` to ensure 1688 * the property is setup correctly. This method calls 1689 * `getPropertyDescriptor` internally to get a descriptor to install. 1690 * To customize what properties do when they are get or set, override 1691 * `getPropertyDescriptor`. To customize the options for a property, 1692 * implement `createProperty` like this: 1693 * 1694 * static createProperty(name, options) { 1695 * options = Object.assign(options, {myOption: true}); 1696 * super.createProperty(name, options); 1697 * } 1698 * 1699 * @nocollapse 1700 */ 1701 static createProperty(name, options = defaultPropertyDeclaration) { 1702 // Note, since this can be called by the `@property` decorator which 1703 // is called before `finalize`, we ensure storage exists for property 1704 // metadata. 1705 this._ensureClassProperties(); 1706 this._classProperties.set(name, options); 1707 // Do not generate an accessor if the prototype already has one, since 1708 // it would be lost otherwise and that would never be the user's intention; 1709 // Instead, we expect users to call `requestUpdate` themselves from 1710 // user-defined accessors. Note that if the super has an accessor we will 1711 // still overwrite it 1712 if (options.noAccessor || this.prototype.hasOwnProperty(name)) { 1713 return; 1714 } 1715 const key = typeof name === 'symbol' ? Symbol() : `__${name}`; 1716 const descriptor = this.getPropertyDescriptor(name, key, options); 1717 if (descriptor !== undefined) { 1718 Object.defineProperty(this.prototype, name, descriptor); 1719 } 1720 } 1721 /** 1722 * Returns a property descriptor to be defined on the given named property. 1723 * If no descriptor is returned, the property will not become an accessor. 1724 * For example, 1725 * 1726 * class MyElement extends LitElement { 1727 * static getPropertyDescriptor(name, key, options) { 1728 * const defaultDescriptor = 1729 * super.getPropertyDescriptor(name, key, options); 1730 * const setter = defaultDescriptor.set; 1731 * return { 1732 * get: defaultDescriptor.get, 1733 * set(value) { 1734 * setter.call(this, value); 1735 * // custom action. 1736 * }, 1737 * configurable: true, 1738 * enumerable: true 1739 * } 1740 * } 1741 * } 1742 * 1743 * @nocollapse 1744 */ 1745 static getPropertyDescriptor(name, key, options) { 1746 return { 1747 // tslint:disable-next-line:no-any no symbol in index 1748 get() { 1749 return this[key]; 1750 }, 1751 set(value) { 1752 const oldValue = this[name]; 1753 this[key] = value; 1754 this 1755 .requestUpdateInternal(name, oldValue, options); 1756 }, 1757 configurable: true, 1758 enumerable: true 1759 }; 1760 } 1761 /** 1762 * Returns the property options associated with the given property. 1763 * These options are defined with a PropertyDeclaration via the `properties` 1764 * object or the `@property` decorator and are registered in 1765 * `createProperty(...)`. 1766 * 1767 * Note, this method should be considered "final" and not overridden. To 1768 * customize the options for a given property, override `createProperty`. 1769 * 1770 * @nocollapse 1771 * @final 1772 */ 1773 static getPropertyOptions(name) { 1774 return this._classProperties && this._classProperties.get(name) || 1775 defaultPropertyDeclaration; 1776 } 1777 /** 1778 * Creates property accessors for registered properties and ensures 1779 * any superclasses are also finalized. 1780 * @nocollapse 1781 */ 1782 static finalize() { 1783 // finalize any superclasses 1784 const superCtor = Object.getPrototypeOf(this); 1785 if (!superCtor.hasOwnProperty(finalized)) { 1786 superCtor.finalize(); 1787 } 1788 this[finalized] = true; 1789 this._ensureClassProperties(); 1790 // initialize Map populated in observedAttributes 1791 this._attributeToPropertyMap = new Map(); 1792 // make any properties 1793 // Note, only process "own" properties since this element will inherit 1794 // any properties defined on the superClass, and finalization ensures 1795 // the entire prototype chain is finalized. 1796 if (this.hasOwnProperty(JSCompiler_renameProperty('properties', this))) { 1797 const props = this.properties; 1798 // support symbols in properties (IE11 does not support this) 1799 const propKeys = [ 1800 ...Object.getOwnPropertyNames(props), 1801 ...(typeof Object.getOwnPropertySymbols === 'function') ? 1802 Object.getOwnPropertySymbols(props) : 1803 [] 1804 ]; 1805 // This for/of is ok because propKeys is an array 1806 for (const p of propKeys) { 1807 // note, use of `any` is due to TypeSript lack of support for symbol in 1808 // index types 1809 // tslint:disable-next-line:no-any no symbol in index 1810 this.createProperty(p, props[p]); 1811 } 1812 } 1813 } 1814 /** 1815 * Returns the property name for the given attribute `name`. 1816 * @nocollapse 1817 */ 1818 static _attributeNameForProperty(name, options) { 1819 const attribute = options.attribute; 1820 return attribute === false ? 1821 undefined : 1822 (typeof attribute === 'string' ? 1823 attribute : 1824 (typeof name === 'string' ? name.toLowerCase() : undefined)); 1825 } 1826 /** 1827 * Returns true if a property should request an update. 1828 * Called when a property value is set and uses the `hasChanged` 1829 * option for the property if present or a strict identity check. 1830 * @nocollapse 1831 */ 1832 static _valueHasChanged(value, old, hasChanged = notEqual) { 1833 return hasChanged(value, old); 1834 } 1835 /** 1836 * Returns the property value for the given attribute value. 1837 * Called via the `attributeChangedCallback` and uses the property's 1838 * `converter` or `converter.fromAttribute` property option. 1839 * @nocollapse 1840 */ 1841 static _propertyValueFromAttribute(value, options) { 1842 const type = options.type; 1843 const converter = options.converter || defaultConverter; 1844 const fromAttribute = (typeof converter === 'function' ? converter : converter.fromAttribute); 1845 return fromAttribute ? fromAttribute(value, type) : value; 1846 } 1847 /** 1848 * Returns the attribute value for the given property value. If this 1849 * returns undefined, the property will *not* be reflected to an attribute. 1850 * If this returns null, the attribute will be removed, otherwise the 1851 * attribute will be set to the value. 1852 * This uses the property's `reflect` and `type.toAttribute` property options. 1853 * @nocollapse 1854 */ 1855 static _propertyValueToAttribute(value, options) { 1856 if (options.reflect === undefined) { 1857 return; 1858 } 1859 const type = options.type; 1860 const converter = options.converter; 1861 const toAttribute = converter && converter.toAttribute || 1862 defaultConverter.toAttribute; 1863 return toAttribute(value, type); 1864 } 1865 /** 1866 * Performs element initialization. By default captures any pre-set values for 1867 * registered properties. 1868 */ 1869 initialize() { 1870 this._updateState = 0; 1871 this._updatePromise = 1872 new Promise((res) => this._enableUpdatingResolver = res); 1873 this._changedProperties = new Map(); 1874 this._saveInstanceProperties(); 1875 // ensures first update will be caught by an early access of 1876 // `updateComplete` 1877 this.requestUpdateInternal(); 1878 } 1879 /** 1880 * Fixes any properties set on the instance before upgrade time. 1881 * Otherwise these would shadow the accessor and break these properties. 1882 * The properties are stored in a Map which is played back after the 1883 * constructor runs. Note, on very old versions of Safari (<=9) or Chrome 1884 * (<=41), properties created for native platform properties like (`id` or 1885 * `name`) may not have default values set in the element constructor. On 1886 * these browsers native properties appear on instances and therefore their
1887 * default value will overwrite any element default (e.g. if the element sets 1888 * this.id = 'id' in the constructor, the 'id' will become '' since this is 1889 * the native platform default). 1890 */ 1891 _saveInstanceProperties() { 1892 // Use forEach so this works even if for/of loops are compiled to for loops 1893 // expecting arrays 1894 this.constructor 1895 ._classProperties.forEach((_v, p) => { 1896 if (this.hasOwnProperty(p)) { 1897 const value = this[p]; 1898 delete this[p]; 1899 if (!this._instanceProperties) { 1900 this._instanceProperties = new Map(); 1901 } 1902 this._instanceProperties.set(p, value); 1903 } 1904 }); 1905 } 1906 /** 1907 * Applies previously saved instance properties. 1908 */ 1909 _applyInstanceProperties() { 1910 // Use forEach so this works even if for/of loops are compiled to for loops 1911 // expecting arrays 1912 // tslint:disable-next-line:no-any 1913 this._instanceProperties.forEach((v, p) => this[p] = v); 1914 this._instanceProperties = undefined; 1915 } 1916 connectedCallback() { 1917 // Ensure first connection completes an update. Updates cannot complete 1918 // before connection. 1919 this.enableUpdating(); 1920 } 1921 enableUpdating() { 1922 if (this._enableUpdatingResolver !== undefined) { 1923 this._enableUpdatingResolver(); 1924 this._enableUpdatingResolver = undefined; 1925 } 1926 } 1927 /** 1928 * Allows for `super.disconnectedCallback()` in extensions while 1929 * reserving the possibility of making non-breaking feature additions 1930 * when disconnecting at some point in the future. 1931 */ 1932 disconnectedCallback() { 1933 } 1934 /** 1935 * Synchronizes property values when attributes change. 1936 */ 1937 attributeChangedCallback(name, old, value) { 1938 if (old !== value) { 1939 this._attributeToProperty(name, value); 1940 } 1941 } 1942 _propertyToAttribute(name, value, options = defaultPropertyDeclaration) { 1943 const ctor = this.constructor; 1944 const attr = ctor._attributeNameForProperty(name, options); 1945 if (attr !== undefined) { 1946 const attrValue = ctor._propertyValueToAttribute(value, options); 1947 // an undefined value does not change the attribute. 1948 if (attrValue === undefined) { 1949 return; 1950 } 1951 // Track if the property is being reflected to avoid 1952 // setting the property again via `attributeChangedCallback`. Note: 1953 // 1. this takes advantage of the fact that the callback is synchronous. 1954 // 2. will behave incorrectly if multiple attributes are in the reaction 1955 // stack at time of calling. However, since we process attributes 1956 // in `update` this should not be possible (or an extreme corner case 1957 // that we'd like to discover). 1958 // mark state reflecting 1959 this._updateState = this._updateState | STATE_IS_REFLECTING_TO_ATTRIBUTE; 1960 if (attrValue == null) { 1961 this.removeAttribute(attr); 1962 } 1963 else { 1964 this.setAttribute(attr, attrValue); 1965 } 1966 // mark state not reflecting 1967 this._updateState = this._updateState & ~STATE_IS_REFLECTING_TO_ATTRIBUTE; 1968 } 1969 } 1970 _attributeToProperty(name, value) { 1971 // Use tracking info to avoid deserializing attribute value if it was 1972 // just set from a property setter. 1973 if (this._updateState & STATE_IS_REFLECTING_TO_ATTRIBUTE) { 1974 return; 1975 } 1976 const ctor = this.constructor; 1977 // Note, hint this as an `AttributeMap` so closure clearly understands 1978 // the type; it has issues with tracking types through statics 1979 // tslint:disable-next-line:no-unnecessary-type-assertion 1980 const propName = ctor._attributeToPropertyMap.get(name); 1981 if (propName !== undefined) { 1982 const options = ctor.getPropertyOptions(propName); 1983 // mark state reflecting 1984 this._updateState = this._updateState | STATE_IS_REFLECTING_TO_PROPERTY; 1985 this[propName] = 1986 // tslint:disable-next-line:no-any 1987 ctor._propertyValueFromAttribute(value, options); 1988 // mark state not reflecting 1989 this._updateState = this._updateState & ~STATE_IS_REFLECTING_TO_PROPERTY; 1990 } 1991 } 1992 /** 1993 * This protected version of `requestUpdate` does not access or return the 1994 * `updateComplete` promise. This promise can be overridden and is therefore 1995 * not free to access. 1996 */ 1997 requestUpdateInternal(name, oldValue, options) { 1998 let shouldRequestUpdate = true; 1999 // If we have a property key, perform property update steps. 2000 if (name !== undefined) { 2001 const ctor = this.constructor; 2002 options = options || ctor.getPropertyOptions(name); 2003 if (ctor._valueHasChanged(this[name], oldValue, options.hasChanged)) { 2004 if (!this._changedProperties.has(name)) { 2005 this._changedProperties.set(name, oldValue); 2006 } 2007 // Add to reflecting properties set. 2008 // Note, it's important that every change has a chance to add the 2009 // property to `_reflectingProperties`. This ensures setting 2010 // attribute + property reflects correctly. 2011 if (options.reflect === true && 2012 !(this._updateState & STATE_IS_REFLECTING_TO_PROPERTY)) { 2013 if (this._reflectingProperties === undefined) { 2014 this._reflectingProperties = new Map(); 2015 } 2016 this._reflectingProperties.set(name, options); 2017 } 2018 } 2019 else { 2020 // Abort the request if the property should not be considered changed. 2021 shouldRequestUpdate = false;
2022 } 2023 } 2024 if (!this._hasRequestedUpdate && shouldRequestUpdate) { 2025 this._updatePromise = this._enqueueUpdate(); 2026 } 2027 } 2028 /** 2029 * Requests an update which is processed asynchronously. This should 2030 * be called when an element should update based on some state not triggered 2031 * by setting a property. In this case, pass no arguments. It should also be 2032 * called when manually implementing a property setter. In this case, pass the 2033 * property `name` and `oldValue` to ensure that any configured property 2034 * options are honored. Returns the `updateComplete` Promise which is resolved 2035 * when the update completes. 2036 * 2037 * @param name {PropertyKey} (optional) name of requesting property 2038 * @param oldValue {any} (optional) old value of requesting property 2039 * @returns {Promise} A Promise that is resolved when the update completes. 2040 */ 2041 requestUpdate(name, oldValue) { 2042 this.requestUpdateInternal(name, oldValue); 2043 return this.updateComplete; 2044 } 2045 /** 2046 * Sets up the element to asynchronously update. 2047 */ 2048 async _enqueueUpdate() { 2049 this._updateState = this._updateState | STATE_UPDATE_REQUESTED; 2050 try { 2051 // Ensure any previous update has resolved before updating. 2052 // This `await` also ensures that property changes are batched. 2053 await this._updatePromise; 2054 } 2055 catch (e) { 2056 // Ignore any previous errors. We only care that the previous cycle is 2057 // done. Any error should have been handled in the previous update. 2058 } 2059 const result = this.performUpdate(); 2060 // If `performUpdate` returns a Promise, we await it. This is done to 2061 // enable coordinating updates with a scheduler. Note, the result is 2062 // checked to avoid delaying an additional microtask unless we need to. 2063 if (result != null) { 2064 await result; 2065 } 2066 return !this._hasRequestedUpdate; 2067 } 2068 get _hasRequestedUpdate() { 2069 return (this._updateState & STATE_UPDATE_REQUESTED); 2070 } 2071 get hasUpdated() { 2072 return (this._updateState & STATE_HAS_UPDATED); 2073 } 2074 /** 2075 * Performs an element update. Note, if an exception is thrown during the 2076 * update, `firstUpdated` and `updated` will not be called. 2077 * 2078 * You can override this method to change the timing of updates. If this 2079 * method is overridden, `super.performUpdate()` must be called. 2080 * 2081 * For instance, to schedule updates to occur just before the next frame: 2082 * 2083 * ``` 2084 * protected async performUpdate(): Promise<unknown> { 2085 * await new Promise((resolve) => requestAnimationFrame(() => resolve())); 2086 * super.performUpdate(); 2087 * } 2088 * ``` 2089 */ 2090 performUpdate() { 2091 // Abort any update if one is not pending when this is called. 2092 // This can happen if `performUpdate` is called early to "flush" 2093 // the update. 2094 if (!this._hasRequestedUpdate) { 2095 return; 2096 } 2097 // Mixin instance properties once, if they exist. 2098 if (this._instanceProperties) { 2099 this._applyInstanceProperties(); 2100 } 2101 let shouldUpdate = false; 2102 const changedProperties = this._changedProperties; 2103 try { 2104 shouldUpdate = this.shouldUpdate(changedProperties); 2105 if (shouldUpdate) { 2106 this.update(changedProperties); 2107 } 2108 else { 2109 this._markUpdated(); 2110 } 2111 } 2112 catch (e) { 2113 // Prevent `firstUpdated` and `updated` from running when there's an 2114 // update exception. 2115 shouldUpdate = false; 2116 // Ensure element can accept additional updates after an exception. 2117 this._markUpdated(); 2118 throw e; 2119 } 2120 if (shouldUpdate) { 2121 if (!(this._updateState & STATE_HAS_UPDATED)) { 2122 this._updateState = this._updateState | STATE_HAS_UPDATED; 2123 this.firstUpdated(changedProperties); 2124 } 2125 this.updated(changedProperties); 2126 } 2127 } 2128 _markUpdated() { 2129 this._changedProperties = new Map(); 2130 this._updateState = this._updateState & ~STATE_UPDATE_REQUESTED; 2131 } 2132 /** 2133 * Returns a Promise that resolves when the element has completed updating. 2134 * The Promise value is a boolean that is `true` if the element completed the 2135 * update without triggering another update. The Promise result is `false` if 2136 * a property was set inside `updated()`. If the Promise is rejected, an 2137 * exception was thrown during the update. 2138 * 2139 * To await additional asynchronous work, override the `_getUpd
2139ateComplete` 2140 * method. For example, it is sometimes useful to await a rendered element 2141 * before fulfilling this Promise. To do this, first await 2142 * `super._getUpdateComplete()`, then any subsequent state. 2143 * 2144 * @returns {Promise} The Promise returns a boolean that indicates if the 2145 * update resolved without triggering another update. 2146 */ 2147 get updateComplete() { 2148 return this._getUpdateComplete(); 2149 } 2150 /** 2151 * Override point for the `updateComplete` promise. 2152 * 2153 * It is not safe to override the `updateComplete` getter directly due to a 2154 * limitation in TypeScript which means it is not possible to call a 2155 * superclass getter (e.g. `super.updateComplete.then(...)`) when the target 2156 * language is ES5 (https://github.com/microsoft/TypeScript/issues/338). 2157 * This method should be overridden instead. For example: 2158 * 2159 * class MyElement extends LitElement { 2160 * async _getUpdateComplete() { 2161 * await super._getUpdateComplete(); 2162 * await this._myChild.updateComplete; 2163 * } 2164 * } 2165 */
2166 _getUpdateComplete() { 2167 return this._updatePromise; 2168 } 2169 /** 2170 * Controls whether or not `update` should be called when the element requests 2171 * an update. By default, this method always returns `true`, but this can be 2172 * customized to control when to update. 2173 * 2174 * @param _changedProperties Map of changed properties with old values 2175 */ 2176 shouldUpdate(_changedProperties) { 2177 return true; 2178 } 2179 /** 2180 * Updates the element. This method reflects property values to attributes. 2181 * It can be overridden to render and keep updated element DOM. 2182 * Setting properties inside this method will *not* trigger 2183 * another update. 2184 * 2185 * @param _changedProperties Map of changed properties with old values 2186 */ 2187 update(_changedProperties) { 2188 if (this._reflectingProperties !== undefined && 2189 this._reflectingProperties.size > 0) { 2190 // Use forEach so this works even if for/of loops are compiled to for 2191 // loops expecting arrays 2192 this._reflectingProperties.forEach((v, k) => this._propertyToAttribute(k, this[k], v)); 2193 this._reflectingProperties = undefined; 2194 } 2195 this._markUpdated(); 2196 } 2197 /** 2198 * Invoked whenever the element is updated. Implement to perform 2199 * post-updating tasks via DOM APIs, for example, focusing an element. 2200 * 2201 * Setting properties inside this method will trigger the element to update 2202 * again after this update cycle completes. 2203 * 2204 * @param _changedProperties Map of changed properties with old values 2205 */ 2206 updated(_changedProperties) { 2207 } 2208 /** 2209 * Invoked when the element is first updated. Implement to perform one time 2210 * work on the element after update. 2211 * 2212 * Setting properties inside this method will trigger the element to update 2213 * again after this update cycle completes. 2214 * 2215 * @param _changedProperties Map of changed properties with old values 2216 */ 2217 firstUpdated(_changedProperties) { 2218 } 2219} 2220_a = finalized; 2221/** 2222 * Marks class as having finished creating properties. 2223 */ 2224UpdatingElement[_a] = true; 2225 2226/** 2227 * @license 2228 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 2229 * This code may only be used under the BSD style license found at 2230 * http://polymer.github.io/LICENSE.txt 2231 * The complete set of authors may be found at 2232 * http://polymer.github.io/AUTHORS.txt 2233 * The complete set of contributors may be found at 2234 * http://polymer.github.io/CONTRIBUTORS.txt 2235 * Code distributed by Google as part of the polymer project is also 2236 * subject to an additional IP rights grant found at 2237 * http://polymer.github.io/PATENTS.txt 2238 */ 2239const legacyCustomElement = (tagName, clazz) => { 2240 window.customElements.define(tagName, clazz); 2241 // Cast as any because TS doesn't recognize the return type as being a 2242 // subtype of the decorated class when clazz is typed as 2243 // `Constructor<HTMLElement>` for some reason. 2244 // `Constructor<HTMLElement>` is helpful to make sure the decorator is 2245 // applied to elements however. 2246 // tslint:disable-next-line:no-any 2247 return clazz; 2248}; 2249const standardCustomElement = (tagName, descriptor) => { 2250 const { kind, elements } = descriptor; 2251 return { 2252 kind, 2253 elements, 2254 // This callback is called once the class is otherwise fully defined 2255 finisher(clazz) { 2256 window.customElements.define(tagName, clazz); 2257 } 2258 }; 2259}; 2260/** 2261 * Class decorator factory that defines the decorated class as a custom element. 2262 * 2263 * ``` 2264 * @customElement('my-element') 2265 * class MyElement { 2266 * render() { 2267 * return html``; 2268 * } 2269 * } 2270 * ``` 2271 * @category Decorator 2272 * @param tagName The name of the custom element to define. 2273 */ 2274const customElement = (tagName) => (classOrDescriptor) => (typeof classOrDescriptor === 'function') ? 2275 legacyCustomElement(tagName, classOrDescriptor) : 2276 standardCustomElement(tagName, classOrDescriptor); 2277const standardProperty = (options, element) => { 2278 // When decorating an accessor, pass it through and add property metadata.
2279 // Note, the `hasOwnProperty` check in `createProperty` ensures we don't 2280 // stomp over the user's accessor. 2281 if (element.kind === 'method' && element.descriptor && 2282 !('value' in element.descriptor)) { 2283 return Object.assign(Object.assign({}, element), { finisher(clazz) { 2284 clazz.createProperty(element.key, options); 2285 } }); 2286 } 2287 else { 2288 // createProperty() takes care of defining the property, but we still 2289 // must return some kind of descriptor, so return a descriptor for an 2290 // unused prototype field. The finisher calls createProperty(). 2291 return { 2292 kind: 'field', 2293 key: Symbol(), 2294 placement: 'own', 2295 descriptor: {}, 2296 // When @babel/plugin-proposal-decorators implements initializers, 2297 // do this instead of the initializer below. See: 2298 // https://github.com/babel/babel/issues/9260 extras: [ 2299 // { 2300 // kind: 'initializer', 2301 // placement: 'own', 2302 // initializer: descriptor.initializer, 2303 // } 2304 // ], 2305 initializer() { 2306 if (typeof element.initializer === 'function') { 2307 this[element.key] = element.initializer.call(this); 2308 } 2309 }, 2310 finisher(clazz) { 2311 clazz.createProperty(element.key, options); 2312 } 2313 }; 2314 } 2315}; 2316const legacyProperty = (options, proto, name) => { 2317 proto.constructor 2318 .createProperty(name, options); 2319}; 2320/** 2321 * A property decorator which creates a LitElement property which reflects a 2322 * corresponding attribute value. A [[`PropertyDeclaration`]] may optionally be 2323 * supplied to configure property features. 2324 * 2325 * This decorator should only be used for public fields. Private or protected 2326 * fields should use the [[`internalProperty`]] decorator. 2327 * 2328 * @example 2329 * ```ts 2330 * class MyElement { 2331 * @property({ type: Boolean }) 2332 * clicked = false; 2333 * } 2334 * ``` 2335 * @category Decorator 2336 * @ExportDecoratedItems 2337 */ 2338function property(options) { 2339 // tslint:disable-next-line:no-any decorator 2340 return (protoOrDescriptor, name) => (name !== undefined) ? 2341 legacyProperty(options, protoOrDescriptor, name) : 2342 standardProperty(options, protoOrDescriptor); 2343} 2344/** 2345 * Declares a private or protected property that still triggers updates to the 2346 * element when it changes. 2347 * 2348 * Properties declared this way must not be used from HTML or HTML templating 2349 * systems, they're solely for properties internal to the element. These 2350 * properties may be renamed by optimization tools like closure compiler. 2351 * @category Decorator 2352 */ 2353function internalProperty(options) { 2354 return property({ attribute: false, hasChanged: options === null || options === void 0 ? void 0 : options.hasChanged }); 2355} 2356 2357/** 2358@license 2359Copyright (c) 2019 The Polymer Project Authors. All rights reserved. 2360This code may only be used under the BSD style license found at 2361http://polymer.github.io/LICENSE.txt The complete set of authors may be found at 2362http://polymer.github.io/AUTHORS.txt The complete set of contributors may be 2363found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as 2364part of the polymer project is also subject to an additional IP rights grant 2365found at http://polymer.github.io/PATENTS.txt 2366*/ 2367/** 2368 * Whether the current browser supports `adoptedStyleSheets`. 2369 */ 2370const supportsAdoptingStyleSheets = (window.ShadowRoot) && 2371 (window.ShadyCSS === undefined || window.ShadyCSS.nativeShadow) && 2372 ('adoptedStyleSheets' in Document.prototype) && 2373 ('replace' in CSSStyleSheet.prototype); 2374const constructionToken = Symbol(); 2375class CSSResult { 2376 constructor(cssText, safeToken) { 2377 if (safeToken !== constructionToken) { 2378 throw new Error('CSSResult is not constructable. Use `unsafeCSS` or `css` instead.'); 2379 } 2380 this.cssText = cssText; 2381 } 2382 // Note, this is a getter so that it's lazy. In practice, this means 2383 // stylesheets are not created until the first element instance is made. 2384 get styleSheet() { 2385 if (this._styleSheet === undefined) { 2386 // Note, if `supportsAdoptingStyleSheets` is true then we assume 2387 // CSSStyleSheet is constructable. 2388 if (supportsAdoptingStyleSheets) { 2389 this._styleSheet = new CSSStyleSheet(); 2390 this._styleSheet.replaceSync(this.cssText); 2391 } 2392 else { 2393 this._styleSheet = null; 2394 } 2395 } 2396 return this._styleSheet; 2397 } 2398 toString() { 2399 return this.cssText; 2400 } 2401} 2402/** 2403 * Wrap a value for interpolation in a [[`css`]] tagged template literal. 2404 * 2405 * This is unsafe because untrusted CSS text can be used to phone home 2406 * or exfiltrate data to an attacker controlled site. Take care to only use 2407 * this with trusted input. 2408 */ 2409const unsafeCSS = (value) => { 2410 return new CSSResult(String(value), constructionToken); 2411}; 2412const textFromCSSResult = (value) => { 2413 if (value instanceof CSSResult) { 2414 return value.cssText; 2415 } 2416 else if (typeof value === 'number') { 2417 return value; 2418 } 2419 else { 2420 throw new Error(`Value passed to 'css' function must be a 'css' function result: ${value}. Use 'unsafeCSS' to pass non-literal values, but 2421 take care to ensure page security.`); 2422 } 2423}; 2424/** 2425 * Template tag which which can be used with LitElement's [[LitElement.styles | 2426 * `styles`]] property to set element styles. For security reasons, only literal 2427 * string values may be used. To incorporate non-literal values [[`unsafeCSS`]] 2428 * may be used inside a template string part. 2429 */ 2430const css = (strings, ...values) => { 2431 const cssText = values.reduce((acc, v, idx) => acc + textFromCSSResult(v) + strings[idx + 1], strings[0]); 2432 return new CSSResult(cssText, constructionToken); 2433}; 2434 2435/** 2436 * @license 2437 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 2438 * This code may only be used under the BSD style license found at 2439 * http://polymer.github.io/LICENSE.txt 2440 * The complete set of authors may be found at 2441 * http://polymer.github.io/AUTHORS.txt 2442 * The complete set of contributors may be found at 2443 * http://polymer.github.io/CONTRIBUTORS.txt 2444 * Code distributed by Google as part of the polymer project is also 2445 * subject to an additional IP rights grant found at 2446 * http://polymer.github.io/PATENTS.txt 2447 */ 2448// IMPORTANT: do not change the property name or the assignment expression.
2449// This line will be used in regexes to search for LitElement usage. 2450// TODO(justinfagnani): inject version number at build time 2451(window['litElementVersions'] || (window['litElementVersions'] = [])) 2452 .push('2.4.0'); 2453/** 2454 * Sentinal value used to avoid calling lit-html's render function when 2455 * subclasses do not implement `render` 2456 */ 2457const renderNotImplemented = {}; 2458/** 2459 * Base element class that manages element properties and attributes, and 2460 * renders a lit-html template. 2461 * 2462 * To define a component, subclass `LitElement` and implement a 2463 * `render` method to provide the component's template. Define properties 2464 * using the [[`properties`]] property or the [[`property`]] decorator. 2465 */ 2466class LitElement extends UpdatingElement { 2467 /** 2468 * Return the array of styles to apply to the element. 2469 * Override this method to integrate into a style management system. 2470 * 2471 * @nocollapse 2472 */ 2473 static getStyles() { 2474 return this.styles; 2475 } 2476 /** @nocollapse */ 2477 static _getUniqueStyles() { 2478 // Only gather styles once per class 2479 if (this.hasOwnProperty(JSCompiler_renameProperty('_styles', this))) { 2480 return; 2481 }
2482 // Take care not to call `this.getStyles()` multiple times since this 2483 // generates new CSSResults each time. 2484 // TODO(sorvell): Since we do not cache CSSResults by input, any 2485 // shared styles will generate new stylesheet objects, which is wasteful. 2486 // This should be addressed when a browser ships constructable 2487 // stylesheets. 2488 const userStyles = this.getStyles(); 2489 if (Array.isArray(userStyles)) { 2490 // De-duplicate styles preserving the _last_ instance in the set. 2491 // This is a performance optimization to avoid duplicated styles that can 2492 // occur especially when composing via subclassing. 2493 // The last item is kept to try to preserve the cascade order with the 2494 // assumption that it's most important that last added styles override 2495 // previous styles. 2496 const addStyles = (styles, set) => styles.reduceRight((set, s) => 2497 // Note: On IE set.add() does not return the set 2498 Array.isArray(s) ? addStyles(s, set) : (set.add(s), set), set); 2499 // Array.from does not work on Set in IE, otherwise return 2500 // Array.from(addStyles(userStyles, new Set<CSSResult>())).reverse() 2501 const set = addStyles(userStyles, new Set()); 2502 const styles = []; 2503 set.forEach((v) => styles.unshift(v)); 2504 this._styles = styles; 2505 } 2506 else { 2507 this._styles = userStyles === undefined ? [] : [userStyles]; 2508 } 2509 // Ensure that there are no invalid CSSStyleSheet instances here. They are 2510 // invalid in two conditions. 2511 // (1) the sheet is non-constructible (`sheet` of a HTMLStyleElement), but 2512 // this is impossible to check except via .replaceSync or use 2513 // (2) the ShadyCSS polyfill is enabled (:. supportsAdoptingStyleSheets is 2514 // false) 2515 this._styles = this._styles.map((s) => { 2516 if (s instanceof CSSStyleSheet && !supportsAdoptingStyleSheets) { 2517 // Flatten the cssText from the passed constructible stylesheet (or 2518 // undetectable non-constructible stylesheet). The user might have 2519 // expected to update their stylesheets over time, but the alternative 2520 // is a crash. 2521 const cssText = Array.prototype.slice.call(s.cssRules) 2522 .reduce((css, rule) => css + rule.cssText, ''); 2523 return unsafeCSS(cssText); 2524 } 2525 return s; 2526 }); 2527 } 2528 /** 2529 * Performs element initialization. By default this calls 2530 * [[`createRenderRoot`]] to create the element [[`renderRoot`]] node and 2531 * captures any pre-set values for registered properties. 2532 */ 2533 initialize() { 2534 super.initialize(); 2535 this.constructor._getUniqueStyles(); 2536 this.renderRoot = this.createRenderRoot(); 2537 // Note, if renderRoot is not a shadowRoot, styles would/could apply to the 2538 // element's getRootNode(). While this could be done, we're choosing not to 2539 // support this now since it would require different logic around de-duping. 2540 if (window.ShadowRoot && this.renderRoot instanceof window.ShadowRoot) { 2541 this.adoptStyles(); 2542 } 2543 } 2544 /** 2545 * Returns the node into which the element should render and by default 2546 * creates and returns an open shadowRoot. Implement to customize where the 2547 * element's DOM is rendered. For example, to render into the element's 2548 * childNodes, return `this`. 2549 * @returns {Element|DocumentFragment} Returns a node into which to render. 2550 */ 2551 createRenderRoot() { 2552 return this.attachShadow({ mode: 'open' }); 2553 } 2554 /** 2555 * Applies styling to the element shadowRoot using the [[`styles`]] 2556 * property. Styling will apply using `shadowRoot.adoptedStyleSheets` where 2557 * available and will fallback otherwise. When Shadow DOM is polyfilled, 2558 * ShadyCSS scopes styles and adds them to the document. When Shadow DOM 2559 * is available but `adoptedStyleSheets` is not, styles are appended to the 2560 * end of the `shadowRoot` to [mimic spec 2561 * behavior](https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets). 2562 */ 2563 adoptStyles() { 2564 const styles = this.constructor._styles; 2565 if (styles.length === 0) { 2566 return; 2567 } 2568 // There are three separate cases here based on Shadow DOM support. 2569 // (1) shadowRoot polyfilled: use ShadyCSS 2570 // (2) shadowRoot.adoptedStyleSheets available: use it 2571 // (3) shadowRoot.adoptedStyleSheets polyfilled: append styles after 2572 // rendering 2573 if (window.ShadyCSS !== undefined && !window.ShadyCSS.nativeShadow) { 2574 window.ShadyCSS.ScopingShim.prepareAdoptedCssText(styles.map((s) => s.cssText), this.localName); 2575 } 2576 else if (supportsAdoptingStyleSheets) { 2577 this.renderRoot.adoptedStyleSheets = 2578 styles.map((s) => s instanceof CSSStyleSheet ? s : s.styleSheet); 2579 } 2580 else { 2581 // This must be done after rendering so the actual style insertion is done 2582 // in `update`. 2583 this._needsShimAdoptedStyleSheets = true; 2584 } 2585 } 2586 connectedCallback() { 2587 super.connectedCallback(); 2588 // Note, first update/render handles styleElement so we only call this if 2589 // connected after first update. 2590 if (this.hasUpdated && window.ShadyCSS !== undefined) { 2591 window.ShadyCSS.styleElement(this); 2592 } 2593 } 2594 /** 2595 * Updates the element. This method reflects property values to attributes 2596 * and calls `render` to render DOM via lit-html. Setting properties inside 2597 * this method will *not* trigger another update. 2598 * @param _changedProperties Map of changed properties with old values 2599 */ 2600 update(changedProperties) { 2601 // Setting properties in `render` should not trigger an update. Since 2602 // updates are allowed after super.update, it's important to call `render` 2603 // before that. 2604 const templateResult = this.render(); 2605 super.update(changedProperties); 2606 // If render is not implemented by the component, don't call lit-html render 2607 if (templateResult !== renderNotImplemented) { 2608 this.constructor 2609 .render(templateResult, this.renderRoot, { scopeName: this.localName, eventContext: this }); 2610 }
2611 // When native Shadow DOM is used but adoptedStyles are not supported, 2612 // insert styling after rendering to ensure adoptedStyles have highest 2613 // priority. 2614 if (this._needsShimAdoptedStyleSheets) { 2615 this._needsShimAdoptedStyleSheets = false; 2616 this.constructor._styles.forEach((s) => { 2617 const style = document.createElement('style'); 2618 style.textContent = s.cssText; 2619 this.renderRoot.appendChild(style); 2620 }); 2621 } 2622 } 2623 /** 2624 * Invoked on each update to perform rendering tasks. This method may return 2625 * any value renderable by lit-html's `NodePart` - typically a 2626 * `TemplateResult`. Setting properties inside this method will *not* trigger 2627 * the element to update. 2628 */ 2629 render() { 2630 return renderNotImplemented; 2631 } 2632} 2633/** 2634 * Ensure this class is marked as `finalized` as an optimization ensuring 2635 * it will not needlessly try to `finalize`. 2636 * 2637 * Note this property name is a string to prevent breaking Closure JS Compiler 2638 * optimizations. See updating-element.ts for more information. 2639 */ 2640LitElement['finalized'] = true; 2641/** 2642 * Reference to the underlying library method used to render the element's 2643 * DOM. By default, points to the `render` method from lit-html's shady-render 2644 * module. 2645 * 2646 * **Most users will never need to touch this property.** 2647 * 2648 * This property should not be confused with the `render` instance method, 2649 * which should be overridden to define a template for the element. 2650 * 2651 * Advanced users creating a new base class based on LitElement can override 2652 * this property to point to a custom render method with a signature that 2653 * matches [shady-render's `render` 2654 * method](https://lit-html.polymer-project.org/api/modules/shady_render.html#render). 2655 * 2656 * @nocollapse 2657 */ 2658LitElement.render = render$1; 2659 2660export { LitElement, css, customElement, html, internalProperty, property };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.