@gluon/gluon 2.5.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/gluon.umd.js DELETED
@@ -1,1591 +0,0 @@
1
- /**
2
- * @license
3
- * MIT License
4
- *
5
- * Copyright (c) 2018 Goffert van Gool
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in all
15
- * copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
- * SOFTWARE.
24
- */
25
-
26
- (function (global, factory) {
27
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
28
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
29
- (factory((global.GluonJS = {})));
30
- }(this, (function (exports) { 'use strict';
31
-
32
- /**
33
- * @license
34
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
35
- * This code may only be used under the BSD style license found at
36
- * http://polymer.github.io/LICENSE.txt
37
- * The complete set of authors may be found at
38
- * http://polymer.github.io/AUTHORS.txt
39
- * The complete set of contributors may be found at
40
- * http://polymer.github.io/CONTRIBUTORS.txt
41
- * Code distributed by Google as part of the polymer project is also
42
- * subject to an additional IP rights grant found at
43
- * http://polymer.github.io/PATENTS.txt
44
- */
45
- /**
46
- * True if the custom elements polyfill is in use.
47
- */
48
- const isCEPolyfill = window.customElements !== undefined &&
49
- window.customElements.polyfillWrapFlushCallback !==
50
- undefined;
51
- /**
52
- * Reparents nodes, starting from `startNode` (inclusive) to `endNode`
53
- * (exclusive), into another container (could be the same container), before
54
- * `beforeNode`. If `beforeNode` is null, it appends the nodes to the
55
- * container.
56
- */
57
-
58
- /**
59
- * Removes nodes, starting from `startNode` (inclusive) to `endNode`
60
- * (exclusive), from `container`.
61
- */
62
- const removeNodes = (container, startNode, endNode = null) => {
63
- let node = startNode;
64
- while (node !== endNode) {
65
- const n = node.nextSibling;
66
- container.removeChild(node);
67
- node = n;
68
- }
69
- };
70
-
71
- /**
72
- * @license
73
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
74
- * This code may only be used under the BSD style license found at
75
- * http://polymer.github.io/LICENSE.txt
76
- * The complete set of authors may be found at
77
- * http://polymer.github.io/AUTHORS.txt
78
- * The complete set of contributors may be found at
79
- * http://polymer.github.io/CONTRIBUTORS.txt
80
- * Code distributed by Google as part of the polymer project is also
81
- * subject to an additional IP rights grant found at
82
- * http://polymer.github.io/PATENTS.txt
83
- */
84
- /**
85
- * An expression marker with embedded unique key to avoid collision with
86
- * possible text in templates.
87
- */
88
- const marker = `{{lit-${String(Math.random()).slice(2)}}}`;
89
- /**
90
- * An expression marker used text-positions, multi-binding attributes, and
91
- * attributes with markup-like text values.
92
- */
93
- const nodeMarker = `<!--${marker}-->`;
94
- const markerRegex = new RegExp(`${marker}|${nodeMarker}`);
95
- /**
96
- * Suffix appended to all bound attribute names.
97
- */
98
- const boundAttributeSuffix = '$lit$';
99
- /**
100
- * An updateable Template that tracks the location of dynamic parts.
101
- */
102
- class Template {
103
- constructor(result, element) {
104
- this.parts = [];
105
- this.element = element;
106
- let index = -1;
107
- let partIndex = 0;
108
- const nodesToRemove = [];
109
- const _prepareTemplate = (template) => {
110
- const content = template.content;
111
- // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be
112
- // null
113
- const walker = document.createTreeWalker(content, 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */, null, false);
114
- // Keeps track of the last index associated with a part. We try to delete
115
- // unnecessary nodes, but we never want to associate two different parts
116
- // to the same index. They must have a constant node between.
117
- let lastPartIndex = 0;
118
- while (walker.nextNode()) {
119
- index++;
120
- const node = walker.currentNode;
121
- if (node.nodeType === 1 /* Node.ELEMENT_NODE */) {
122
- if (node.hasAttributes()) {
123
- const attributes = node.attributes;
124
- // Per
125
- // https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap,
126
- // attributes are not guaranteed to be returned in document order.
127
- // In particular, Edge/IE can return them out of order, so we cannot
128
- // assume a correspondance between part index and attribute index.
129
- let count = 0;
130
- for (let i = 0; i < attributes.length; i++) {
131
- if (attributes[i].value.indexOf(marker) >= 0) {
132
- count++;
133
- }
134
- }
135
- while (count-- > 0) {
136
- // Get the template literal section leading up to the first
137
- // expression in this attribute
138
- const stringForPart = result.strings[partIndex];
139
- // Find the attribute name
140
- const name = lastAttributeNameRegex.exec(stringForPart)[2];
141
- // Find the corresponding attribute
142
- // All bound attributes have had a suffix added in
143
- // TemplateResult#getHTML to opt out of special attribute
144
- // handling. To look up the attribute value we also need to add
145
- // the suffix.
146
- const attributeLookupName = name.toLowerCase() + boundAttributeSuffix;
147
- const attributeValue = node.getAttribute(attributeLookupName);
148
- const strings = attributeValue.split(markerRegex);
149
- this.parts.push({ type: 'attribute', index, name, strings });
150
- node.removeAttribute(attributeLookupName);
151
- partIndex += strings.length - 1;
152
- }
153
- }
154
- if (node.tagName === 'TEMPLATE') {
155
- _prepareTemplate(node);
156
- }
157
- }
158
- else if (node.nodeType === 3 /* Node.TEXT_NODE */) {
159
- const data = node.data;
160
- if (data.indexOf(marker) >= 0) {
161
- const parent = node.parentNode;
162
- const strings = data.split(markerRegex);
163
- const lastIndex = strings.length - 1;
164
- // Generate a new text node for each literal section
165
- // These nodes are also used as the markers for node parts
166
- for (let i = 0; i < lastIndex; i++) {
167
- parent.insertBefore((strings[i] === '') ? createMarker() :
168
- document.createTextNode(strings[i]), node);
169
- this.parts.push({ type: 'node', index: ++index });
170
- }
171
- // If there's no text, we must insert a comment to mark our place.
172
- // Else, we can trust it will stick around after cloning.
173
- if (strings[lastIndex] === '') {
174
- parent.insertBefore(createMarker(), node);
175
- nodesToRemove.push(node);
176
- }
177
- else {
178
- node.data = strings[lastIndex];
179
- }
180
- // We have a part for each match found
181
- partIndex += lastIndex;
182
- }
183
- }
184
- else if (node.nodeType === 8 /* Node.COMMENT_NODE */) {
185
- if (node.data === marker) {
186
- const parent = node.parentNode;
187
- // Add a new marker node to be the startNode of the Part if any of
188
- // the following are true:
189
- // * We don't have a previousSibling
190
- // * The previousSibling is already the start of a previous part
191
- if (node.previousSibling === null || index === lastPartIndex) {
192
- index++;
193
- parent.insertBefore(createMarker(), node);
194
- }
195
- lastPartIndex = index;
196
- this.parts.push({ type: 'node', index });
197
- // If we don't have a nextSibling, keep this node so we have an end.
198
- // Else, we can remove it to save future costs.
199
- if (node.nextSibling === null) {
200
- node.data = '';
201
- }
202
- else {
203
- nodesToRemove.push(node);
204
- index--;
205
- }
206
- partIndex++;
207
- }
208
- else {
209
- let i = -1;
210
- while ((i = node.data.indexOf(marker, i + 1)) !==
211
- -1) {
212
- // Comment node has a binding marker inside, make an inactive part
213
- // The binding won't work, but subsequent bindings will
214
- // TODO (justinfagnani): consider whether it's even worth it to
215
- // make bindings in comments work
216
- this.parts.push({ type: 'node', index: -1 });
217
- }
218
- }
219
- }
220
- }
221
- };
222
- _prepareTemplate(element);
223
- // Remove text binding nodes after the walk to not disturb the TreeWalker
224
- for (const n of nodesToRemove) {
225
- n.parentNode.removeChild(n);
226
- }
227
- }
228
- }
229
- const isTemplatePartActive = (part) => part.index !== -1;
230
- // Allows `document.createComment('')` to be renamed for a
231
- // small manual size-savings.
232
- const createMarker = () => document.createComment('');
233
- /**
234
- * This regex extracts the attribute name preceding an attribute-position
235
- * expression. It does this by matching the syntax allowed for attributes
236
- * against the string literal directly preceding the expression, assuming that
237
- * the expression is in an attribute-value position.
238
- *
239
- * See attributes in the HTML spec:
240
- * https://www.w3.org/TR/html5/syntax.html#attributes-0
241
- *
242
- * "\0-\x1F\x7F-\x9F" are Unicode control characters
243
- *
244
- * " \x09\x0a\x0c\x0d" are HTML space characters:
245
- * https://www.w3.org/TR/html5/infrastructure.html#space-character
246
- *
247
- * So an attribute is:
248
- * * The name: any character except a control character, space character, ('),
249
- * ("), ">", "=", or "/"
250
- * * Followed by zero or more space characters
251
- * * Followed by "="
252
- * * Followed by zero or more space characters
253
- * * Followed by:
254
- * * Any character except space, ('), ("), "<", ">", "=", (`), or
255
- * * (") then any non-("), or
256
- * * (') then any non-(')
257
- */
258
- const lastAttributeNameRegex = /([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F \x09\x0a\x0c\x0d"'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/;
259
-
260
- /**
261
- * @license
262
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
263
- * This code may only be used under the BSD style license found at
264
- * http://polymer.github.io/LICENSE.txt
265
- * The complete set of authors may be found at
266
- * http://polymer.github.io/AUTHORS.txt
267
- * The complete set of contributors may be found at
268
- * http://polymer.github.io/CONTRIBUTORS.txt
269
- * Code distributed by Google as part of the polymer project is also
270
- * subject to an additional IP rights grant found at
271
- * http://polymer.github.io/PATENTS.txt
272
- */
273
- /**
274
- * @module shady-render
275
- */
276
- const walkerNodeFilter = 133;
277
- /**
278
- * Removes the list of nodes from a Template safely. In addition to removing
279
- * nodes from the Template, the Template part indices are updated to match
280
- * the mutated Template DOM.
281
- *
282
- * As the template is walked the removal state is tracked and
283
- * part indices are adjusted as needed.
284
- *
285
- * div
286
- * div#1 (remove) <-- start removing (removing node is div#1)
287
- * div
288
- * div#2 (remove) <-- continue removing (removing node is still div#1)
289
- * div
290
- * div <-- stop removing since previous sibling is the removing node (div#1,
291
- * removed 4 nodes)
292
- */
293
- function removeNodesFromTemplate(template, nodesToRemove) {
294
- const { element: { content }, parts } = template;
295
- const walker = document.createTreeWalker(content, walkerNodeFilter, null, false);
296
- let partIndex = nextActiveIndexInTemplateParts(parts);
297
- let part = parts[partIndex];
298
- let nodeIndex = -1;
299
- let removeCount = 0;
300
- const nodesToRemoveInTemplate = [];
301
- let currentRemovingNode = null;
302
- while (walker.nextNode()) {
303
- nodeIndex++;
304
- const node = walker.currentNode;
305
- // End removal if stepped past the removing node
306
- if (node.previousSibling === currentRemovingNode) {
307
- currentRemovingNode = null;
308
- }
309
- // A node to remove was found in the template
310
- if (nodesToRemove.has(node)) {
311
- nodesToRemoveInTemplate.push(node);
312
- // Track node we're removing
313
- if (currentRemovingNode === null) {
314
- currentRemovingNode = node;
315
- }
316
- }
317
- // When removing, increment count by which to adjust subsequent part indices
318
- if (currentRemovingNode !== null) {
319
- removeCount++;
320
- }
321
- while (part !== undefined && part.index === nodeIndex) {
322
- // If part is in a removed node deactivate it by setting index to -1 or
323
- // adjust the index as needed.
324
- part.index = currentRemovingNode !== null ? -1 : part.index - removeCount;
325
- // go to the next active part.
326
- partIndex = nextActiveIndexInTemplateParts(parts, partIndex);
327
- part = parts[partIndex];
328
- }
329
- }
330
- nodesToRemoveInTemplate.forEach((n) => n.parentNode.removeChild(n));
331
- }
332
- const countNodes = (node) => {
333
- let count = (node.nodeType === 11 /* Node.DOCUMENT_FRAGMENT_NODE */) ? 0 : 1;
334
- const walker = document.createTreeWalker(node, walkerNodeFilter, null, false);
335
- while (walker.nextNode()) {
336
- count++;
337
- }
338
- return count;
339
- };
340
- const nextActiveIndexInTemplateParts = (parts, startIndex = -1) => {
341
- for (let i = startIndex + 1; i < parts.length; i++) {
342
- const part = parts[i];
343
- if (isTemplatePartActive(part)) {
344
- return i;
345
- }
346
- }
347
- return -1;
348
- };
349
- /**
350
- * Inserts the given node into the Template, optionally before the given
351
- * refNode. In addition to inserting the node into the Template, the Template
352
- * part indices are updated to match the mutated Template DOM.
353
- */
354
- function insertNodeIntoTemplate(template, node, refNode = null) {
355
- const { element: { content }, parts } = template;
356
- // If there's no refNode, then put node at end of template.
357
- // No part indices need to be shifted in this case.
358
- if (refNode === null || refNode === undefined) {
359
- content.appendChild(node);
360
- return;
361
- }
362
- const walker = document.createTreeWalker(content, walkerNodeFilter, null, false);
363
- let partIndex = nextActiveIndexInTemplateParts(parts);
364
- let insertCount = 0;
365
- let walkerIndex = -1;
366
- while (walker.nextNode()) {
367
- walkerIndex++;
368
- const walkerNode = walker.currentNode;
369
- if (walkerNode === refNode) {
370
- insertCount = countNodes(node);
371
- refNode.parentNode.insertBefore(node, refNode);
372
- }
373
- while (partIndex !== -1 && parts[partIndex].index === walkerIndex) {
374
- // If we've inserted the node, simply adjust all subsequent parts
375
- if (insertCount > 0) {
376
- while (partIndex !== -1) {
377
- parts[partIndex].index += insertCount;
378
- partIndex = nextActiveIndexInTemplateParts(parts, partIndex);
379
- }
380
- return;
381
- }
382
- partIndex = nextActiveIndexInTemplateParts(parts, partIndex);
383
- }
384
- }
385
- }
386
-
387
- /**
388
- * @license
389
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
390
- * This code may only be used under the BSD style license found at
391
- * http://polymer.github.io/LICENSE.txt
392
- * The complete set of authors may be found at
393
- * http://polymer.github.io/AUTHORS.txt
394
- * The complete set of contributors may be found at
395
- * http://polymer.github.io/CONTRIBUTORS.txt
396
- * Code distributed by Google as part of the polymer project is also
397
- * subject to an additional IP rights grant found at
398
- * http://polymer.github.io/PATENTS.txt
399
- */
400
- const directives = new WeakMap();
401
- /**
402
- * Brands a function as a directive so that lit-html will call the function
403
- * during template rendering, rather than passing as a value.
404
- *
405
- * @param f The directive factory function. Must be a function that returns a
406
- * function of the signature `(part: Part) => void`. The returned function will
407
- * be called with the part object
408
- *
409
- * @example
410
- *
411
- * ```
412
- * import {directive, html} from 'lit-html';
413
- *
414
- * const immutable = directive((v) => (part) => {
415
- * if (part.value !== v) {
416
- * part.setValue(v)
417
- * }
418
- * });
419
- * ```
420
- */
421
- // tslint:disable-next-line:no-any
422
-
423
- const isDirective = (o) => {
424
- return typeof o === 'function' && directives.has(o);
425
- };
426
-
427
- /**
428
- * @license
429
- * Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
430
- * This code may only be used under the BSD style license found at
431
- * http://polymer.github.io/LICENSE.txt
432
- * The complete set of authors may be found at
433
- * http://polymer.github.io/AUTHORS.txt
434
- * The complete set of contributors may be found at
435
- * http://polymer.github.io/CONTRIBUTORS.txt
436
- * Code distributed by Google as part of the polymer project is also
437
- * subject to an additional IP rights grant found at
438
- * http://polymer.github.io/PATENTS.txt
439
- */
440
- /**
441
- * A sentinel value that signals that a value was handled by a directive and
442
- * should not be written to the DOM.
443
- */
444
- const noChange = {};
445
- /**
446
- * A sentinel value that signals a NodePart to fully clear its content.
447
- */
448
- const nothing = {};
449
-
450
- /**
451
- * @license
452
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
453
- * This code may only be used under the BSD style license found at
454
- * http://polymer.github.io/LICENSE.txt
455
- * The complete set of authors may be found at
456
- * http://polymer.github.io/AUTHORS.txt
457
- * The complete set of contributors may be found at
458
- * http://polymer.github.io/CONTRIBUTORS.txt
459
- * Code distributed by Google as part of the polymer project is also
460
- * subject to an additional IP rights grant found at
461
- * http://polymer.github.io/PATENTS.txt
462
- */
463
- /**
464
- * @module lit-html
465
- */
466
- /**
467
- * An instance of a `Template` that can be attached to the DOM and updated
468
- * with new values.
469
- */
470
- class TemplateInstance {
471
- constructor(template, processor, options) {
472
- this._parts = [];
473
- this.template = template;
474
- this.processor = processor;
475
- this.options = options;
476
- }
477
- update(values) {
478
- let i = 0;
479
- for (const part of this._parts) {
480
- if (part !== undefined) {
481
- part.setValue(values[i]);
482
- }
483
- i++;
484
- }
485
- for (const part of this._parts) {
486
- if (part !== undefined) {
487
- part.commit();
488
- }
489
- }
490
- }
491
- _clone() {
492
- // When using the Custom Elements polyfill, clone the node, rather than
493
- // importing it, to keep the fragment in the template's document. This
494
- // leaves the fragment inert so custom elements won't upgrade and
495
- // potentially modify their contents by creating a polyfilled ShadowRoot
496
- // while we traverse the tree.
497
- const fragment = isCEPolyfill ?
498
- this.template.element.content.cloneNode(true) :
499
- document.importNode(this.template.element.content, true);
500
- const parts = this.template.parts;
501
- let partIndex = 0;
502
- let nodeIndex = 0;
503
- const _prepareInstance = (fragment) => {
504
- // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be
505
- // null
506
- const walker = document.createTreeWalker(fragment, 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */, null, false);
507
- let node = walker.nextNode();
508
- // Loop through all the nodes and parts of a template
509
- while (partIndex < parts.length && node !== null) {
510
- const part = parts[partIndex];
511
- // Consecutive Parts may have the same node index, in the case of
512
- // multiple bound attributes on an element. So each iteration we either
513
- // increment the nodeIndex, if we aren't on a node with a part, or the
514
- // partIndex if we are. By not incrementing the nodeIndex when we find a
515
- // part, we allow for the next part to be associated with the current
516
- // node if neccessasry.
517
- if (!isTemplatePartActive(part)) {
518
- this._parts.push(undefined);
519
- partIndex++;
520
- }
521
- else if (nodeIndex === part.index) {
522
- if (part.type === 'node') {
523
- const part = this.processor.handleTextExpression(this.options);
524
- part.insertAfterNode(node.previousSibling);
525
- this._parts.push(part);
526
- }
527
- else {
528
- this._parts.push(...this.processor.handleAttributeExpressions(node, part.name, part.strings, this.options));
529
- }
530
- partIndex++;
531
- }
532
- else {
533
- nodeIndex++;
534
- if (node.nodeName === 'TEMPLATE') {
535
- _prepareInstance(node.content);
536
- }
537
- node = walker.nextNode();
538
- }
539
- }
540
- };
541
- _prepareInstance(fragment);
542
- if (isCEPolyfill) {
543
- document.adoptNode(fragment);
544
- customElements.upgrade(fragment);
545
- }
546
- return fragment;
547
- }
548
- }
549
-
550
- /**
551
- * @license
552
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
553
- * This code may only be used under the BSD style license found at
554
- * http://polymer.github.io/LICENSE.txt
555
- * The complete set of authors may be found at
556
- * http://polymer.github.io/AUTHORS.txt
557
- * The complete set of contributors may be found at
558
- * http://polymer.github.io/CONTRIBUTORS.txt
559
- * Code distributed by Google as part of the polymer project is also
560
- * subject to an additional IP rights grant found at
561
- * http://polymer.github.io/PATENTS.txt
562
- */
563
- /**
564
- * @module lit-html
565
- */
566
- /**
567
- * The return type of `html`, which holds a Template and the values from
568
- * interpolated expressions.
569
- */
570
- class TemplateResult {
571
- constructor(strings, values, type, processor) {
572
- this.strings = strings;
573
- this.values = values;
574
- this.type = type;
575
- this.processor = processor;
576
- }
577
- /**
578
- * Returns a string of HTML used to create a `<template>` element.
579
- */
580
- getHTML() {
581
- const endIndex = this.strings.length - 1;
582
- let html = '';
583
- for (let i = 0; i < endIndex; i++) {
584
- const s = this.strings[i];
585
- // This exec() call does two things:
586
- // 1) Appends a suffix to the bound attribute name to opt out of special
587
- // attribute value parsing that IE11 and Edge do, like for style and
588
- // many SVG attributes. The Template class also appends the same suffix
589
- // when looking up attributes to create Parts.
590
- // 2) Adds an unquoted-attribute-safe marker for the first expression in
591
- // an attribute. Subsequent attribute expressions will use node markers,
592
- // and this is safe since attributes with multiple expressions are
593
- // guaranteed to be quoted.
594
- const match = lastAttributeNameRegex.exec(s);
595
- if (match) {
596
- // We're starting a new bound attribute.
597
- // Add the safe attribute suffix, and use unquoted-attribute-safe
598
- // marker.
599
- html += s.substr(0, match.index) + match[1] + match[2] +
600
- boundAttributeSuffix + match[3] + marker;
601
- }
602
- else {
603
- // We're either in a bound node, or trailing bound attribute.
604
- // Either way, nodeMarker is safe to use.
605
- html += s + nodeMarker;
606
- }
607
- }
608
- return html + this.strings[endIndex];
609
- }
610
- getTemplateElement() {
611
- const template = document.createElement('template');
612
- template.innerHTML = this.getHTML();
613
- return template;
614
- }
615
- }
616
- /**
617
- * A TemplateResult for SVG fragments.
618
- *
619
- * This class wraps HTMl in an `<svg>` tag in order to parse its contents in the
620
- * SVG namespace, then modifies the template to remove the `<svg>` tag so that
621
- * clones only container the original fragment.
622
- */
623
-
624
- /**
625
- * @license
626
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
627
- * This code may only be used under the BSD style license found at
628
- * http://polymer.github.io/LICENSE.txt
629
- * The complete set of authors may be found at
630
- * http://polymer.github.io/AUTHORS.txt
631
- * The complete set of contributors may be found at
632
- * http://polymer.github.io/CONTRIBUTORS.txt
633
- * Code distributed by Google as part of the polymer project is also
634
- * subject to an additional IP rights grant found at
635
- * http://polymer.github.io/PATENTS.txt
636
- */
637
- /**
638
- * @module lit-html
639
- */
640
- const isPrimitive = (value) => {
641
- return (value === null ||
642
- !(typeof value === 'object' || typeof value === 'function'));
643
- };
644
- /**
645
- * Sets attribute values for AttributeParts, so that the value is only set once
646
- * even if there are multiple parts for an attribute.
647
- */
648
- class AttributeCommitter {
649
- constructor(element, name, strings) {
650
- this.dirty = true;
651
- this.element = element;
652
- this.name = name;
653
- this.strings = strings;
654
- this.parts = [];
655
- for (let i = 0; i < strings.length - 1; i++) {
656
- this.parts[i] = this._createPart();
657
- }
658
- }
659
- /**
660
- * Creates a single part. Override this to create a differnt type of part.
661
- */
662
- _createPart() {
663
- return new AttributePart(this);
664
- }
665
- _getValue() {
666
- const strings = this.strings;
667
- const l = strings.length - 1;
668
- let text = '';
669
- for (let i = 0; i < l; i++) {
670
- text += strings[i];
671
- const part = this.parts[i];
672
- if (part !== undefined) {
673
- const v = part.value;
674
- if (v != null &&
675
- (Array.isArray(v) ||
676
- // tslint:disable-next-line:no-any
677
- typeof v !== 'string' && v[Symbol.iterator])) {
678
- for (const t of v) {
679
- text += typeof t === 'string' ? t : String(t);
680
- }
681
- }
682
- else {
683
- text += typeof v === 'string' ? v : String(v);
684
- }
685
- }
686
- }
687
- text += strings[l];
688
- return text;
689
- }
690
- commit() {
691
- if (this.dirty) {
692
- this.dirty = false;
693
- this.element.setAttribute(this.name, this._getValue());
694
- }
695
- }
696
- }
697
- class AttributePart {
698
- constructor(comitter) {
699
- this.value = undefined;
700
- this.committer = comitter;
701
- }
702
- setValue(value) {
703
- if (value !== noChange && (!isPrimitive(value) || value !== this.value)) {
704
- this.value = value;
705
- // If the value is a not a directive, dirty the committer so that it'll
706
- // call setAttribute. If the value is a directive, it'll dirty the
707
- // committer if it calls setValue().
708
- if (!isDirective(value)) {
709
- this.committer.dirty = true;
710
- }
711
- }
712
- }
713
- commit() {
714
- while (isDirective(this.value)) {
715
- const directive$$1 = this.value;
716
- this.value = noChange;
717
- directive$$1(this);
718
- }
719
- if (this.value === noChange) {
720
- return;
721
- }
722
- this.committer.commit();
723
- }
724
- }
725
- class NodePart {
726
- constructor(options) {
727
- this.value = undefined;
728
- this._pendingValue = undefined;
729
- this.options = options;
730
- }
731
- /**
732
- * Inserts this part into a container.
733
- *
734
- * This part must be empty, as its contents are not automatically moved.
735
- */
736
- appendInto(container) {
737
- this.startNode = container.appendChild(createMarker());
738
- this.endNode = container.appendChild(createMarker());
739
- }
740
- /**
741
- * Inserts this part between `ref` and `ref`'s next sibling. Both `ref` and
742
- * its next sibling must be static, unchanging nodes such as those that appear
743
- * in a literal section of a template.
744
- *
745
- * This part must be empty, as its contents are not automatically moved.
746
- */
747
- insertAfterNode(ref) {
748
- this.startNode = ref;
749
- this.endNode = ref.nextSibling;
750
- }
751
- /**
752
- * Appends this part into a parent part.
753
- *
754
- * This part must be empty, as its contents are not automatically moved.
755
- */
756
- appendIntoPart(part) {
757
- part._insert(this.startNode = createMarker());
758
- part._insert(this.endNode = createMarker());
759
- }
760
- /**
761
- * Appends this part after `ref`
762
- *
763
- * This part must be empty, as its contents are not automatically moved.
764
- */
765
- insertAfterPart(ref) {
766
- ref._insert(this.startNode = createMarker());
767
- this.endNode = ref.endNode;
768
- ref.endNode = this.startNode;
769
- }
770
- setValue(value) {
771
- this._pendingValue = value;
772
- }
773
- commit() {
774
- while (isDirective(this._pendingValue)) {
775
- const directive$$1 = this._pendingValue;
776
- this._pendingValue = noChange;
777
- directive$$1(this);
778
- }
779
- const value = this._pendingValue;
780
- if (value === noChange) {
781
- return;
782
- }
783
- if (isPrimitive(value)) {
784
- if (value !== this.value) {
785
- this._commitText(value);
786
- }
787
- }
788
- else if (value instanceof TemplateResult) {
789
- this._commitTemplateResult(value);
790
- }
791
- else if (value instanceof Node) {
792
- this._commitNode(value);
793
- }
794
- else if (Array.isArray(value) ||
795
- // tslint:disable-next-line:no-any
796
- value[Symbol.iterator]) {
797
- this._commitIterable(value);
798
- }
799
- else if (value === nothing) {
800
- this.value = nothing;
801
- this.clear();
802
- }
803
- else {
804
- // Fallback, will render the string representation
805
- this._commitText(value);
806
- }
807
- }
808
- _insert(node) {
809
- this.endNode.parentNode.insertBefore(node, this.endNode);
810
- }
811
- _commitNode(value) {
812
- if (this.value === value) {
813
- return;
814
- }
815
- this.clear();
816
- this._insert(value);
817
- this.value = value;
818
- }
819
- _commitText(value) {
820
- const node = this.startNode.nextSibling;
821
- value = value == null ? '' : value;
822
- if (node === this.endNode.previousSibling &&
823
- node.nodeType === 3 /* Node.TEXT_NODE */) {
824
- // If we only have a single text node between the markers, we can just
825
- // set its value, rather than replacing it.
826
- // TODO(justinfagnani): Can we just check if this.value is primitive?
827
- node.data = value;
828
- }
829
- else {
830
- this._commitNode(document.createTextNode(typeof value === 'string' ? value : String(value)));
831
- }
832
- this.value = value;
833
- }
834
- _commitTemplateResult(value) {
835
- const template = this.options.templateFactory(value);
836
- if (this.value instanceof TemplateInstance &&
837
- this.value.template === template) {
838
- this.value.update(value.values);
839
- }
840
- else {
841
- // Make sure we propagate the template processor from the TemplateResult
842
- // so that we use its syntax extension, etc. The template factory comes
843
- // from the render function options so that it can control template
844
- // caching and preprocessing.
845
- const instance = new TemplateInstance(template, value.processor, this.options);
846
- const fragment = instance._clone();
847
- instance.update(value.values);
848
- this._commitNode(fragment);
849
- this.value = instance;
850
- }
851
- }
852
- _commitIterable(value) {
853
- // For an Iterable, we create a new InstancePart per item, then set its
854
- // value to the item. This is a little bit of overhead for every item in
855
- // an Iterable, but it lets us recurse easily and efficiently update Arrays
856
- // of TemplateResults that will be commonly returned from expressions like:
857
- // array.map((i) => html`${i}`), by reusing existing TemplateInstances.
858
- // If _value is an array, then the previous render was of an
859
- // iterable and _value will contain the NodeParts from the previous
860
- // render. If _value is not an array, clear this part and make a new
861
- // array for NodeParts.
862
- if (!Array.isArray(this.value)) {
863
- this.value = [];
864
- this.clear();
865
- }
866
- // Lets us keep track of how many items we stamped so we can clear leftover
867
- // items from a previous render
868
- const itemParts = this.value;
869
- let partIndex = 0;
870
- let itemPart;
871
- for (const item of value) {
872
- // Try to reuse an existing part
873
- itemPart = itemParts[partIndex];
874
- // If no existing part, create a new one
875
- if (itemPart === undefined) {
876
- itemPart = new NodePart(this.options);
877
- itemParts.push(itemPart);
878
- if (partIndex === 0) {
879
- itemPart.appendIntoPart(this);
880
- }
881
- else {
882
- itemPart.insertAfterPart(itemParts[partIndex - 1]);
883
- }
884
- }
885
- itemPart.setValue(item);
886
- itemPart.commit();
887
- partIndex++;
888
- }
889
- if (partIndex < itemParts.length) {
890
- // Truncate the parts array so _value reflects the current state
891
- itemParts.length = partIndex;
892
- this.clear(itemPart && itemPart.endNode);
893
- }
894
- }
895
- clear(startNode = this.startNode) {
896
- removeNodes(this.startNode.parentNode, startNode.nextSibling, this.endNode);
897
- }
898
- }
899
- /**
900
- * Implements a boolean attribute, roughly as defined in the HTML
901
- * specification.
902
- *
903
- * If the value is truthy, then the attribute is present with a value of
904
- * ''. If the value is falsey, the attribute is removed.
905
- */
906
- class BooleanAttributePart {
907
- constructor(element, name, strings) {
908
- this.value = undefined;
909
- this._pendingValue = undefined;
910
- if (strings.length !== 2 || strings[0] !== '' || strings[1] !== '') {
911
- throw new Error('Boolean attributes can only contain a single expression');
912
- }
913
- this.element = element;
914
- this.name = name;
915
- this.strings = strings;
916
- }
917
- setValue(value) {
918
- this._pendingValue = value;
919
- }
920
- commit() {
921
- while (isDirective(this._pendingValue)) {
922
- const directive$$1 = this._pendingValue;
923
- this._pendingValue = noChange;
924
- directive$$1(this);
925
- }
926
- if (this._pendingValue === noChange) {
927
- return;
928
- }
929
- const value = !!this._pendingValue;
930
- if (this.value !== value) {
931
- if (value) {
932
- this.element.setAttribute(this.name, '');
933
- }
934
- else {
935
- this.element.removeAttribute(this.name);
936
- }
937
- }
938
- this.value = value;
939
- this._pendingValue = noChange;
940
- }
941
- }
942
- /**
943
- * Sets attribute values for PropertyParts, so that the value is only set once
944
- * even if there are multiple parts for a property.
945
- *
946
- * If an expression controls the whole property value, then the value is simply
947
- * assigned to the property under control. If there are string literals or
948
- * multiple expressions, then the strings are expressions are interpolated into
949
- * a string first.
950
- */
951
- class PropertyCommitter extends AttributeCommitter {
952
- constructor(element, name, strings) {
953
- super(element, name, strings);
954
- this.single =
955
- (strings.length === 2 && strings[0] === '' && strings[1] === '');
956
- }
957
- _createPart() {
958
- return new PropertyPart(this);
959
- }
960
- _getValue() {
961
- if (this.single) {
962
- return this.parts[0].value;
963
- }
964
- return super._getValue();
965
- }
966
- commit() {
967
- if (this.dirty) {
968
- this.dirty = false;
969
- // tslint:disable-next-line:no-any
970
- this.element[this.name] = this._getValue();
971
- }
972
- }
973
- }
974
- class PropertyPart extends AttributePart {
975
- }
976
- // Detect event listener options support. If the `capture` property is read
977
- // from the options object, then options are supported. If not, then the thrid
978
- // argument to add/removeEventListener is interpreted as the boolean capture
979
- // value so we should only pass the `capture` property.
980
- let eventOptionsSupported = false;
981
- try {
982
- const options = {
983
- get capture() {
984
- eventOptionsSupported = true;
985
- return false;
986
- }
987
- };
988
- // tslint:disable-next-line:no-any
989
- window.addEventListener('test', options, options);
990
- // tslint:disable-next-line:no-any
991
- window.removeEventListener('test', options, options);
992
- }
993
- catch (_e) {
994
- }
995
- class EventPart {
996
- constructor(element, eventName, eventContext) {
997
- this.value = undefined;
998
- this._pendingValue = undefined;
999
- this.element = element;
1000
- this.eventName = eventName;
1001
- this.eventContext = eventContext;
1002
- this._boundHandleEvent = (e) => this.handleEvent(e);
1003
- }
1004
- setValue(value) {
1005
- this._pendingValue = value;
1006
- }
1007
- commit() {
1008
- while (isDirective(this._pendingValue)) {
1009
- const directive$$1 = this._pendingValue;
1010
- this._pendingValue = noChange;
1011
- directive$$1(this);
1012
- }
1013
- if (this._pendingValue === noChange) {
1014
- return;
1015
- }
1016
- const newListener = this._pendingValue;
1017
- const oldListener = this.value;
1018
- const shouldRemoveListener = newListener == null ||
1019
- oldListener != null &&
1020
- (newListener.capture !== oldListener.capture ||
1021
- newListener.once !== oldListener.once ||
1022
- newListener.passive !== oldListener.passive);
1023
- const shouldAddListener = newListener != null && (oldListener == null || shouldRemoveListener);
1024
- if (shouldRemoveListener) {
1025
- this.element.removeEventListener(this.eventName, this._boundHandleEvent, this._options);
1026
- }
1027
- if (shouldAddListener) {
1028
- this._options = getOptions(newListener);
1029
- this.element.addEventListener(this.eventName, this._boundHandleEvent, this._options);
1030
- }
1031
- this.value = newListener;
1032
- this._pendingValue = noChange;
1033
- }
1034
- handleEvent(event) {
1035
- if (typeof this.value === 'function') {
1036
- this.value.call(this.eventContext || this.element, event);
1037
- }
1038
- else {
1039
- this.value.handleEvent(event);
1040
- }
1041
- }
1042
- }
1043
- // We copy options because of the inconsistent behavior of browsers when reading
1044
- // the third argument of add/removeEventListener. IE11 doesn't support options
1045
- // at all. Chrome 41 only reads `capture` if the argument is an object.
1046
- const getOptions = (o) => o &&
1047
- (eventOptionsSupported ?
1048
- { capture: o.capture, passive: o.passive, once: o.once } :
1049
- o.capture);
1050
-
1051
- /**
1052
- * @license
1053
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
1054
- * This code may only be used under the BSD style license found at
1055
- * http://polymer.github.io/LICENSE.txt
1056
- * The complete set of authors may be found at
1057
- * http://polymer.github.io/AUTHORS.txt
1058
- * The complete set of contributors may be found at
1059
- * http://polymer.github.io/CONTRIBUTORS.txt
1060
- * Code distributed by Google as part of the polymer project is also
1061
- * subject to an additional IP rights grant found at
1062
- * http://polymer.github.io/PATENTS.txt
1063
- */
1064
- /**
1065
- * The default TemplateFactory which caches Templates keyed on
1066
- * result.type and result.strings.
1067
- */
1068
- function templateFactory(result) {
1069
- let templateCache = templateCaches.get(result.type);
1070
- if (templateCache === undefined) {
1071
- templateCache = {
1072
- stringsArray: new WeakMap(),
1073
- keyString: new Map()
1074
- };
1075
- templateCaches.set(result.type, templateCache);
1076
- }
1077
- let template = templateCache.stringsArray.get(result.strings);
1078
- if (template !== undefined) {
1079
- return template;
1080
- }
1081
- // If the TemplateStringsArray is new, generate a key from the strings
1082
- // This key is shared between all templates with identical content
1083
- const key = result.strings.join(marker);
1084
- // Check if we already have a Template for this key
1085
- template = templateCache.keyString.get(key);
1086
- if (template === undefined) {
1087
- // If we have not seen this key before, create a new Template
1088
- template = new Template(result, result.getTemplateElement());
1089
- // Cache the Template for this key
1090
- templateCache.keyString.set(key, template);
1091
- }
1092
- // Cache all future queries for this TemplateStringsArray
1093
- templateCache.stringsArray.set(result.strings, template);
1094
- return template;
1095
- }
1096
- const templateCaches = new Map();
1097
-
1098
- /**
1099
- * @license
1100
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
1101
- * This code may only be used under the BSD style license found at
1102
- * http://polymer.github.io/LICENSE.txt
1103
- * The complete set of authors may be found at
1104
- * http://polymer.github.io/AUTHORS.txt
1105
- * The complete set of contributors may be found at
1106
- * http://polymer.github.io/CONTRIBUTORS.txt
1107
- * Code distributed by Google as part of the polymer project is also
1108
- * subject to an additional IP rights grant found at
1109
- * http://polymer.github.io/PATENTS.txt
1110
- */
1111
- /**
1112
- * @module lit-html
1113
- */
1114
- const parts = new WeakMap();
1115
- /**
1116
- * Renders a template to a container.
1117
- *
1118
- * To update a container with new values, reevaluate the template literal and
1119
- * call `render` with the new result.
1120
- *
1121
- * @param result a TemplateResult created by evaluating a template tag like
1122
- * `html` or `svg`.
1123
- * @param container A DOM parent to render to. The entire contents are either
1124
- * replaced, or efficiently updated if the same result type was previous
1125
- * rendered there.
1126
- * @param options RenderOptions for the entire render tree rendered to this
1127
- * container. Render options must *not* change between renders to the same
1128
- * container, as those changes will not effect previously rendered DOM.
1129
- */
1130
- const render = (result, container, options) => {
1131
- let part = parts.get(container);
1132
- if (part === undefined) {
1133
- removeNodes(container, container.firstChild);
1134
- parts.set(container, part = new NodePart(Object.assign({ templateFactory }, options)));
1135
- part.appendInto(container);
1136
- }
1137
- part.setValue(result);
1138
- part.commit();
1139
- };
1140
-
1141
- /**
1142
- * @license
1143
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
1144
- * This code may only be used under the BSD style license found at
1145
- * http://polymer.github.io/LICENSE.txt
1146
- * The complete set of authors may be found at
1147
- * http://polymer.github.io/AUTHORS.txt
1148
- * The complete set of contributors may be found at
1149
- * http://polymer.github.io/CONTRIBUTORS.txt
1150
- * Code distributed by Google as part of the polymer project is also
1151
- * subject to an additional IP rights grant found at
1152
- * http://polymer.github.io/PATENTS.txt
1153
- */
1154
- /**
1155
- * Creates Parts when a template is instantiated.
1156
- */
1157
- class DefaultTemplateProcessor {
1158
- /**
1159
- * Create parts for an attribute-position binding, given the event, attribute
1160
- * name, and string literals.
1161
- *
1162
- * @param element The element containing the binding
1163
- * @param name The attribute name
1164
- * @param strings The string literals. There are always at least two strings,
1165
- * event for fully-controlled bindings with a single expression.
1166
- */
1167
- handleAttributeExpressions(element, name, strings, options) {
1168
- const prefix = name[0];
1169
- if (prefix === '.') {
1170
- const comitter = new PropertyCommitter(element, name.slice(1), strings);
1171
- return comitter.parts;
1172
- }
1173
- if (prefix === '@') {
1174
- return [new EventPart(element, name.slice(1), options.eventContext)];
1175
- }
1176
- if (prefix === '?') {
1177
- return [new BooleanAttributePart(element, name.slice(1), strings)];
1178
- }
1179
- const comitter = new AttributeCommitter(element, name, strings);
1180
- return comitter.parts;
1181
- }
1182
- /**
1183
- * Create parts for a text-position binding.
1184
- * @param templateFactory
1185
- */
1186
- handleTextExpression(options) {
1187
- return new NodePart(options);
1188
- }
1189
- }
1190
- const defaultTemplateProcessor = new DefaultTemplateProcessor();
1191
-
1192
- /**
1193
- * @license
1194
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
1195
- * This code may only be used under the BSD style license found at
1196
- * http://polymer.github.io/LICENSE.txt
1197
- * The complete set of authors may be found at
1198
- * http://polymer.github.io/AUTHORS.txt
1199
- * The complete set of contributors may be found at
1200
- * http://polymer.github.io/CONTRIBUTORS.txt
1201
- * Code distributed by Google as part of the polymer project is also
1202
- * subject to an additional IP rights grant found at
1203
- * http://polymer.github.io/PATENTS.txt
1204
- */
1205
- /**
1206
- *
1207
- * Main lit-html module.
1208
- *
1209
- * Main exports:
1210
- *
1211
- * - [[html]]
1212
- * - [[svg]]
1213
- * - [[render]]
1214
- *
1215
- * @module lit-html
1216
- * @preferred
1217
- */
1218
- /**
1219
- * Do not remove this comment; it keeps typedoc from misplacing the module
1220
- * docs.
1221
- */
1222
- // IMPORTANT: do not change the property name or the assignment expression.
1223
- // This line will be used in regexes to search for lit-html usage.
1224
- // TODO(justinfagnani): inject version number at build time
1225
- (window['litHtmlVersions'] || (window['litHtmlVersions'] = [])).push('1.0.0');
1226
- /**
1227
- * Interprets a template literal as an HTML template that can efficiently
1228
- * render to and update a container.
1229
- */
1230
- const html = (strings, ...values) => new TemplateResult(strings, values, 'html', defaultTemplateProcessor);
1231
- /**
1232
- * Interprets a template literal as an SVG template that can efficiently
1233
- * render to and update a container.
1234
- */
1235
-
1236
- /**
1237
- * @license
1238
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
1239
- * This code may only be used under the BSD style license found at
1240
- * http://polymer.github.io/LICENSE.txt
1241
- * The complete set of authors may be found at
1242
- * http://polymer.github.io/AUTHORS.txt
1243
- * The complete set of contributors may be found at
1244
- * http://polymer.github.io/CONTRIBUTORS.txt
1245
- * Code distributed by Google as part of the polymer project is also
1246
- * subject to an additional IP rights grant found at
1247
- * http://polymer.github.io/PATENTS.txt
1248
- */
1249
- /**
1250
- * Module to add shady DOM/shady CSS polyfill support to lit-html template
1251
- * rendering. See the [[render]] method for details.
1252
- *
1253
- * @module shady-render
1254
- * @preferred
1255
- */
1256
- /**
1257
- * Do not remove this comment; it keeps typedoc from misplacing the module
1258
- * docs.
1259
- */
1260
- // Get a key to lookup in `templateCaches`.
1261
- const getTemplateCacheKey = (type, scopeName) => `${type}--${scopeName}`;
1262
- let compatibleShadyCSSVersion = true;
1263
- if (typeof window.ShadyCSS === 'undefined') {
1264
- compatibleShadyCSSVersion = false;
1265
- }
1266
- else if (typeof window.ShadyCSS.prepareTemplateDom === 'undefined') {
1267
- console.warn(`Incompatible ShadyCSS version detected.` +
1268
- `Please update to at least @webcomponents/webcomponentsjs@2.0.2 and` +
1269
- `@webcomponents/shadycss@1.3.1.`);
1270
- compatibleShadyCSSVersion = false;
1271
- }
1272
- /**
1273
- * Template factory which scopes template DOM using ShadyCSS.
1274
- * @param scopeName {string}
1275
- */
1276
- const shadyTemplateFactory = (scopeName) => (result) => {
1277
- const cacheKey = getTemplateCacheKey(result.type, scopeName);
1278
- let templateCache = templateCaches.get(cacheKey);
1279
- if (templateCache === undefined) {
1280
- templateCache = {
1281
- stringsArray: new WeakMap(),
1282
- keyString: new Map()
1283
- };
1284
- templateCaches.set(cacheKey, templateCache);
1285
- }
1286
- let template = templateCache.stringsArray.get(result.strings);
1287
- if (template !== undefined) {
1288
- return template;
1289
- }
1290
- const key = result.strings.join(marker);
1291
- template = templateCache.keyString.get(key);
1292
- if (template === undefined) {
1293
- const element = result.getTemplateElement();
1294
- if (compatibleShadyCSSVersion) {
1295
- window.ShadyCSS.prepareTemplateDom(element, scopeName);
1296
- }
1297
- template = new Template(result, element);
1298
- templateCache.keyString.set(key, template);
1299
- }
1300
- templateCache.stringsArray.set(result.strings, template);
1301
- return template;
1302
- };
1303
- const TEMPLATE_TYPES = ['html', 'svg'];
1304
- /**
1305
- * Removes all style elements from Templates for the given scopeName.
1306
- */
1307
- const removeStylesFromLitTemplates = (scopeName) => {
1308
- TEMPLATE_TYPES.forEach((type) => {
1309
- const templates = templateCaches.get(getTemplateCacheKey(type, scopeName));
1310
- if (templates !== undefined) {
1311
- templates.keyString.forEach((template) => {
1312
- const { element: { content } } = template;
1313
- // IE 11 doesn't support the iterable param Set constructor
1314
- const styles = new Set();
1315
- Array.from(content.querySelectorAll('style')).forEach((s) => {
1316
- styles.add(s);
1317
- });
1318
- removeNodesFromTemplate(template, styles);
1319
- });
1320
- }
1321
- });
1322
- };
1323
- const shadyRenderSet = new Set();
1324
- /**
1325
- * For the given scope name, ensures that ShadyCSS style scoping is performed.
1326
- * This is done just once per scope name so the fragment and template cannot
1327
- * be modified.
1328
- * (1) extracts styles from the rendered fragment and hands them to ShadyCSS
1329
- * to be scoped and appended to the document
1330
- * (2) removes style elements from all lit-html Templates for this scope name.
1331
- *
1332
- * Note, <style> elements can only be placed into templates for the
1333
- * initial rendering of the scope. If <style> elements are included in templates
1334
- * dynamically rendered to the scope (after the first scope render), they will
1335
- * not be scoped and the <style> will be left in the template and rendered
1336
- * output.
1337
- */
1338
- const prepareTemplateStyles = (renderedDOM, template, scopeName) => {
1339
- shadyRenderSet.add(scopeName);
1340
- // Move styles out of rendered DOM and store.
1341
- const styles = renderedDOM.querySelectorAll('style');
1342
- // If there are no styles, skip unnecessary work
1343
- if (styles.length === 0) {
1344
- // Ensure prepareTemplateStyles is called to support adding
1345
- // styles via `prepareAdoptedCssText` since that requires that
1346
- // `prepareTemplateStyles` is called.
1347
- window.ShadyCSS.prepareTemplateStyles(template.element, scopeName);
1348
- return;
1349
- }
1350
- const condensedStyle = document.createElement('style');
1351
- // Collect styles into a single style. This helps us make sure ShadyCSS
1352
- // manipulations will not prevent us from being able to fix up template
1353
- // part indices.
1354
- // NOTE: collecting styles is inefficient for browsers but ShadyCSS
1355
- // currently does this anyway. When it does not, this should be changed.
1356
- for (let i = 0; i < styles.length; i++) {
1357
- const style = styles[i];
1358
- style.parentNode.removeChild(style);
1359
- condensedStyle.textContent += style.textContent;
1360
- }
1361
- // Remove styles from nested templates in this scope.
1362
- removeStylesFromLitTemplates(scopeName);
1363
- // And then put the condensed style into the "root" template passed in as
1364
- // `template`.
1365
- insertNodeIntoTemplate(template, condensedStyle, template.element.content.firstChild);
1366
- // Note, it's important that ShadyCSS gets the template that `lit-html`
1367
- // will actually render so that it can update the style inside when
1368
- // needed (e.g. @apply native Shadow DOM case).
1369
- window.ShadyCSS.prepareTemplateStyles(template.element, scopeName);
1370
- if (window.ShadyCSS.nativeShadow) {
1371
- // When in native Shadow DOM, re-add styling to rendered content using
1372
- // the style ShadyCSS produced.
1373
- const style = template.element.content.querySelector('style');
1374
- renderedDOM.insertBefore(style.cloneNode(true), renderedDOM.firstChild);
1375
- }
1376
- else {
1377
- // When not in native Shadow DOM, at this point ShadyCSS will have
1378
- // removed the style from the lit template and parts will be broken as a
1379
- // result. To fix this, we put back the style node ShadyCSS removed
1380
- // and then tell lit to remove that node from the template.
1381
- // NOTE, ShadyCSS creates its own style so we can safely add/remove
1382
- // `condensedStyle` here.
1383
- template.element.content.insertBefore(condensedStyle, template.element.content.firstChild);
1384
- const removes = new Set();
1385
- removes.add(condensedStyle);
1386
- removeNodesFromTemplate(template, removes);
1387
- }
1388
- };
1389
- /**
1390
- * Extension to the standard `render` method which supports rendering
1391
- * to ShadowRoots when the ShadyDOM (https://github.com/webcomponents/shadydom)
1392
- * and ShadyCSS (https://github.com/webcomponents/shadycss) polyfills are used
1393
- * or when the webcomponentsjs
1394
- * (https://github.com/webcomponents/webcomponentsjs) polyfill is used.
1395
- *
1396
- * Adds a `scopeName` option which is used to scope element DOM and stylesheets
1397
- * when native ShadowDOM is unavailable. The `scopeName` will be added to
1398
- * the class attribute of all rendered DOM. In addition, any style elements will
1399
- * be automatically re-written with this `scopeName` selector and moved out
1400
- * of the rendered DOM and into the document `<head>`.
1401
- *
1402
- * It is common to use this render method in conjunction with a custom element
1403
- * which renders a shadowRoot. When this is done, typically the element's
1404
- * `localName` should be used as the `scopeName`.
1405
- *
1406
- * In addition to DOM scoping, ShadyCSS also supports a basic shim for css
1407
- * custom properties (needed only on older browsers like IE11) and a shim for
1408
- * a deprecated feature called `@apply` that supports applying a set of css
1409
- * custom properties to a given location.
1410
- *
1411
- * Usage considerations:
1412
- *
1413
- * * Part values in `<style>` elements are only applied the first time a given
1414
- * `scopeName` renders. Subsequent changes to parts in style elements will have
1415
- * no effect. Because of this, parts in style elements should only be used for
1416
- * values that will never change, for example parts that set scope-wide theme
1417
- * values or parts which render shared style elements.
1418
- *
1419
- * * Note, due to a limitation of the ShadyDOM polyfill, rendering in a
1420
- * custom element's `constructor` is not supported. Instead rendering should
1421
- * either done asynchronously, for example at microtask timing (for example
1422
- * `Promise.resolve()`), or be deferred until the first time the element's
1423
- * `connectedCallback` runs.
1424
- *
1425
- * Usage considerations when using shimmed custom properties or `@apply`:
1426
- *
1427
- * * Whenever any dynamic changes are made which affect
1428
- * css custom properties, `ShadyCSS.styleElement(element)` must be called
1429
- * to update the element. There are two cases when this is needed:
1430
- * (1) the element is connected to a new parent, (2) a class is added to the
1431
- * element that causes it to match different custom properties.
1432
- * To address the first case when rendering a custom element, `styleElement`
1433
- * should be called in the element's `connectedCallback`.
1434
- *
1435
- * * Shimmed custom properties may only be defined either for an entire
1436
- * shadowRoot (for example, in a `:host` rule) or via a rule that directly
1437
- * matches an element with a shadowRoot. In other words, instead of flowing from
1438
- * parent to child as do native css custom properties, shimmed custom properties
1439
- * flow only from shadowRoots to nested shadowRoots.
1440
- *
1441
- * * When using `@apply` mixing css shorthand property names with
1442
- * non-shorthand names (for example `border` and `border-width`) is not
1443
- * supported.
1444
- */
1445
- const render$1 = (result, container, options) => {
1446
- const scopeName = options.scopeName;
1447
- const hasRendered = parts.has(container);
1448
- const needsScoping = container instanceof ShadowRoot &&
1449
- compatibleShadyCSSVersion && result instanceof TemplateResult;
1450
- // Handle first render to a scope specially...
1451
- const firstScopeRender = needsScoping && !shadyRenderSet.has(scopeName);
1452
- // On first scope render, render into a fragment; this cannot be a single
1453
- // fragment that is reused since nested renders can occur synchronously.
1454
- const renderContainer = firstScopeRender ? document.createDocumentFragment() : container;
1455
- render(result, renderContainer, Object.assign({ templateFactory: shadyTemplateFactory(scopeName) }, options));
1456
- // When performing first scope render,
1457
- // (1) We've rendered into a fragment so that there's a chance to
1458
- // `prepareTemplateStyles` before sub-elements hit the DOM
1459
- // (which might cause them to render based on a common pattern of
1460
- // rendering in a custom element's `connectedCallback`);
1461
- // (2) Scope the template with ShadyCSS one time only for this scope.
1462
- // (3) Render the fragment into the container and make sure the
1463
- // container knows its `part` is the one we just rendered. This ensures
1464
- // DOM will be re-used on subsequent renders.
1465
- if (firstScopeRender) {
1466
- const part = parts.get(renderContainer);
1467
- parts.delete(renderContainer);
1468
- if (part.value instanceof TemplateInstance) {
1469
- prepareTemplateStyles(renderContainer, part.value.template, scopeName);
1470
- }
1471
- removeNodes(container, container.firstChild);
1472
- container.appendChild(renderContainer);
1473
- parts.set(container, part);
1474
- }
1475
- // After elements have hit the DOM, update styling if this is the
1476
- // initial render to this container.
1477
- // This is needed whenever dynamic changes are made so it would be
1478
- // safest to do every render; however, this would regress performance
1479
- // so we leave it up to the user to call `ShadyCSSS.styleElement`
1480
- // for dynamic changes.
1481
- if (!hasRendered && needsScoping) {
1482
- window.ShadyCSS.styleElement(container.host);
1483
- }
1484
- };
1485
-
1486
- // Key to store the HTML tag in a custom element class
1487
- const TAG = Symbol('tag');
1488
-
1489
- // Key to store render status in a custom element instance
1490
- const NEEDSRENDER = Symbol('needsRender');
1491
-
1492
- // Transforms a camelCased string into a kebab-cased string
1493
- const camelToKebab = camel => camel.replace(/([a-z](?=[A-Z]))|([A-Z](?=[A-Z][a-z]))/g, '$1$2-').toLowerCase();
1494
-
1495
- // Creates an ID cache in the `$` property of a custom element instance
1496
- const createIdCache = element => {
1497
- element.$ = {};
1498
- element.renderRoot.querySelectorAll('[id]').forEach(node => {
1499
- element.$[node.id] = node;
1500
- });
1501
- };
1502
-
1503
- /**
1504
- * A lightweight base class for custom elements
1505
- *
1506
- * Features:
1507
- *
1508
- * - Determines an appropriate HTML tagname based on an element's class name
1509
- * - Efficient rendering engine using lit-html (https://github.com/Polymer/lit-html)
1510
- * - Creates a cache for descendant nodes with an `id` in the `$` property
1511
- */
1512
- class GluonElement extends HTMLElement {
1513
- constructor() {
1514
- super();
1515
- this.renderRoot = this.createRenderRoot();
1516
-
1517
- // This ensures that any properties that are set prior to upgrading this element
1518
- // have their instance setters called
1519
- Object.getOwnPropertyNames(this).forEach(property => {
1520
- const propertyValue = this[property];
1521
- delete this[property];
1522
- this[property] = propertyValue;
1523
- });
1524
- }
1525
-
1526
- /**
1527
- * Returns an open shadowRoot as the default rendering root
1528
- *
1529
- * Override this method to provide an alternative rendering root
1530
- * For example, return `this` to render the template as childNodes
1531
- */
1532
- createRenderRoot() {
1533
- return this.attachShadow({ mode: 'open' });
1534
- }
1535
-
1536
- /**
1537
- * Returns the HTML tagname for elements of this class
1538
- *
1539
- * It defaults to the kebab-cased version of the class name. To override,
1540
- * defined a `static get is()` property on your custom element class, and return
1541
- * whatever string you want to use for the HTML tagname
1542
- */
1543
- static get is() {
1544
- return (this.hasOwnProperty(TAG) && this[TAG]) || (this[TAG] = camelToKebab(this.name));
1545
- }
1546
-
1547
- /**
1548
- * Called when an element is connected to the DOM
1549
- *
1550
- * When an element has a `template`, attach a shadowRoot to the element,
1551
- * and render the template. Once the template is rendered, creates an ID cache
1552
- * in the `$` property
1553
- *
1554
- * When adding a `connectedCallback` to your custom element, you should call
1555
- * `super.connectedCallback()` before doing anything other than actions
1556
- * that alter the result of the template rendering.
1557
- */
1558
- connectedCallback() {
1559
- if ('template' in this) {
1560
- this.render({ sync: true });
1561
- createIdCache(this);
1562
- }
1563
- }
1564
-
1565
- /**
1566
- * Renders the template for this element into the shadowRoot
1567
- *
1568
- * @param { sync }: perform a synchronous (blocking) render. The default render
1569
- * is asynchronous, and multiple calls to `render()` are batched by default
1570
- *
1571
- * @returns a Promise that resolves once template has been rendered
1572
- */
1573
- async render({ sync = false } = {}) {
1574
- this[NEEDSRENDER] = true;
1575
- if (!sync) {
1576
- await 0;
1577
- }
1578
- if (this[NEEDSRENDER]) {
1579
- this[NEEDSRENDER] = false;
1580
- render$1(this.template, this.renderRoot, { scopeName: this.constructor.is, eventContext: this });
1581
- }
1582
- }
1583
- }
1584
-
1585
- exports.GluonElement = GluonElement;
1586
- exports.html = html;
1587
-
1588
- Object.defineProperty(exports, '__esModule', { value: true });
1589
-
1590
- })));
1591
- //# sourceMappingURL=gluon.umd.js.map