diff options
Diffstat (limited to 'toolkit/content/widgets/vendor')
-rw-r--r-- | toolkit/content/widgets/vendor/lit.all.mjs | 4467 |
1 files changed, 4467 insertions, 0 deletions
diff --git a/toolkit/content/widgets/vendor/lit.all.mjs b/toolkit/content/widgets/vendor/lit.all.mjs new file mode 100644 index 0000000000..ec542440ae --- /dev/null +++ b/toolkit/content/widgets/vendor/lit.all.mjs @@ -0,0 +1,4467 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const NODE_MODE$1 = false; +const global$2 = window; +/** + * Whether the current browser supports `adoptedStyleSheets`. + */ +const supportsAdoptingStyleSheets = global$2.ShadowRoot && + (global$2.ShadyCSS === undefined || global$2.ShadyCSS.nativeShadow) && + 'adoptedStyleSheets' in Document.prototype && + 'replace' in CSSStyleSheet.prototype; +const constructionToken = Symbol(); +const cssTagCache = new WeakMap(); +/** + * A container for a string of CSS text, that may be used to create a CSSStyleSheet. + * + * CSSResult is the return value of `css`-tagged template literals and + * `unsafeCSS()`. In order to ensure that CSSResults are only created via the + * `css` tag and `unsafeCSS()`, CSSResult cannot be constructed directly. + */ +class CSSResult { + constructor(cssText, strings, safeToken) { + // This property needs to remain unminified. + this['_$cssResult$'] = true; + if (safeToken !== constructionToken) { + throw new Error('CSSResult is not constructable. Use `unsafeCSS` or `css` instead.'); + } + this.cssText = cssText; + this._strings = strings; + } + // This is a getter so that it's lazy. In practice, this means stylesheets + // are not created until the first element instance is made. + get styleSheet() { + // If `supportsAdoptingStyleSheets` is true then we assume CSSStyleSheet is + // constructable. + let styleSheet = this._styleSheet; + const strings = this._strings; + if (supportsAdoptingStyleSheets && styleSheet === undefined) { + const cacheable = strings !== undefined && strings.length === 1; + if (cacheable) { + styleSheet = cssTagCache.get(strings); + } + if (styleSheet === undefined) { + (this._styleSheet = styleSheet = new CSSStyleSheet()).replaceSync(this.cssText); + if (cacheable) { + cssTagCache.set(strings, styleSheet); + } + } + } + return styleSheet; + } + toString() { + return this.cssText; + } +} +const textFromCSSResult = (value) => { + // This property needs to remain unminified. + if (value['_$cssResult$'] === true) { + return value.cssText; + } + else if (typeof value === 'number') { + return value; + } + else { + throw new Error(`Value passed to 'css' function must be a 'css' function result: ` + + `${value}. Use 'unsafeCSS' to pass non-literal values, but take care ` + + `to ensure page security.`); + } +}; +/** + * Wrap a value for interpolation in a {@linkcode css} tagged template literal. + * + * This is unsafe because untrusted CSS text can be used to phone home + * or exfiltrate data to an attacker controlled site. Take care to only use + * this with trusted input. + */ +const unsafeCSS = (value) => new CSSResult(typeof value === 'string' ? value : String(value), undefined, constructionToken); +/** + * A template literal tag which can be used with LitElement's + * {@linkcode LitElement.styles} property to set element styles. + * + * For security reasons, only literal string values and number may be used in + * embedded expressions. To incorporate non-literal values {@linkcode unsafeCSS} + * may be used inside an expression. + */ +const css = (strings, ...values) => { + const cssText = strings.length === 1 + ? strings[0] + : values.reduce((acc, v, idx) => acc + textFromCSSResult(v) + strings[idx + 1], strings[0]); + return new CSSResult(cssText, strings, constructionToken); +}; +/** + * Applies the given styles to a `shadowRoot`. When Shadow DOM is + * available but `adoptedStyleSheets` is not, styles are appended to the + * `shadowRoot` to [mimic spec behavior](https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets). + * Note, when shimming is used, any styles that are subsequently placed into + * the shadowRoot should be placed *before* any shimmed adopted styles. This + * will match spec behavior that gives adopted sheets precedence over styles in + * shadowRoot. + */ +const adoptStyles = (renderRoot, styles) => { + if (supportsAdoptingStyleSheets) { + renderRoot.adoptedStyleSheets = styles.map((s) => s instanceof CSSStyleSheet ? s : s.styleSheet); + } + else { + styles.forEach((s) => { + const style = document.createElement('style'); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const nonce = global$2['litNonce']; + if (nonce !== undefined) { + style.setAttribute('nonce', nonce); + } + style.textContent = s.cssText; + renderRoot.appendChild(style); + }); + } +}; +const cssResultFromStyleSheet = (sheet) => { + let cssText = ''; + for (const rule of sheet.cssRules) { + cssText += rule.cssText; + } + return unsafeCSS(cssText); +}; +const getCompatibleStyle = supportsAdoptingStyleSheets || + (NODE_MODE$1 ) + ? (s) => s + : (s) => s instanceof CSSStyleSheet ? cssResultFromStyleSheet(s) : s; + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +var _d$1; +var _e; +const global$1 = window; +const trustedTypes$1 = global$1 + .trustedTypes; +// Temporary workaround for https://crbug.com/993268 +// Currently, any attribute starting with "on" is considered to be a +// TrustedScript source. Such boolean attributes must be set to the equivalent +// trusted emptyScript value. +const emptyStringForBooleanAttribute$1 = trustedTypes$1 + ? trustedTypes$1.emptyScript + : ''; +const polyfillSupport$2 = global$1.reactiveElementPolyfillSupport; +/* + * When using Closure Compiler, JSCompiler_renameProperty(property, object) is + * replaced at compile time by the munged name for object[property]. We cannot + * alias this function, so we have to use a small shim that has the same + * behavior when not compiling. + */ +/*@__INLINE__*/ +const JSCompiler_renameProperty = (prop, _obj) => prop; +const defaultConverter = { + toAttribute(value, type) { + switch (type) { + case Boolean: + value = value ? emptyStringForBooleanAttribute$1 : null; + break; + case Object: + case Array: + // if the value is `null` or `undefined` pass this through + // to allow removing/no change behavior. + value = value == null ? value : JSON.stringify(value); + break; + } + return value; + }, + fromAttribute(value, type) { + let fromValue = value; + switch (type) { + case Boolean: + fromValue = value !== null; + break; + case Number: + fromValue = value === null ? null : Number(value); + break; + case Object: + case Array: + // Do *not* generate exception when invalid JSON is set as elements + // don't normally complain on being mis-configured. + // TODO(sorvell): Do generate exception in *dev mode*. + try { + // Assert to adhere to Bazel's "must type assert JSON parse" rule. + fromValue = JSON.parse(value); + } + catch (e) { + fromValue = null; + } + break; + } + return fromValue; + }, +}; +/** + * Change function that returns true if `value` is different from `oldValue`. + * This method is used as the default for a property's `hasChanged` function. + */ +const notEqual = (value, old) => { + // This ensures (old==NaN, value==NaN) always returns false + return old !== value && (old === old || value === value); +}; +const defaultPropertyDeclaration = { + attribute: true, + type: String, + converter: defaultConverter, + reflect: false, + hasChanged: notEqual, +}; +/** + * The Closure JS Compiler doesn't currently have good support for static + * property semantics where "this" is dynamic (e.g. + * https://github.com/google/closure-compiler/issues/3177 and others) so we use + * this hack to bypass any rewriting by the compiler. + */ +const finalized = 'finalized'; +/** + * Base element class which manages element properties and attributes. When + * properties change, the `update` method is asynchronously called. This method + * should be supplied by subclassers to render updates as desired. + * @noInheritDoc + */ +class ReactiveElement extends HTMLElement { + constructor() { + super(); + this.__instanceProperties = new Map(); + /** + * True if there is a pending update as a result of calling `requestUpdate()`. + * Should only be read. + * @category updates + */ + this.isUpdatePending = false; + /** + * Is set to `true` after the first update. The element code cannot assume + * that `renderRoot` exists before the element `hasUpdated`. + * @category updates + */ + this.hasUpdated = false; + /** + * Name of currently reflecting property + */ + this.__reflectingProperty = null; + this._initialize(); + } + /** + * Adds an initializer function to the class that is called during instance + * construction. + * + * This is useful for code that runs against a `ReactiveElement` + * subclass, such as a decorator, that needs to do work for each + * instance, such as setting up a `ReactiveController`. + * + * ```ts + * const myDecorator = (target: typeof ReactiveElement, key: string) => { + * target.addInitializer((instance: ReactiveElement) => { + * // This is run during construction of the element + * new MyController(instance); + * }); + * } + * ``` + * + * Decorating a field will then cause each instance to run an initializer + * that adds a controller: + * + * ```ts + * class MyElement extends LitElement { + * @myDecorator foo; + * } + * ``` + * + * Initializers are stored per-constructor. Adding an initializer to a + * subclass does not add it to a superclass. Since initializers are run in + * constructors, initializers will run in order of the class hierarchy, + * starting with superclasses and progressing to the instance's class. + * + * @nocollapse + */ + static addInitializer(initializer) { + var _a; + this.finalize(); + ((_a = this._initializers) !== null && _a !== void 0 ? _a : (this._initializers = [])).push(initializer); + } + /** + * Returns a list of attributes corresponding to the registered properties. + * @nocollapse + * @category attributes + */ + static get observedAttributes() { + // note: piggy backing on this to ensure we're finalized. + this.finalize(); + const attributes = []; + // Use forEach so this works even if for/of loops are compiled to for loops + // expecting arrays + this.elementProperties.forEach((v, p) => { + const attr = this.__attributeNameForProperty(p, v); + if (attr !== undefined) { + this.__attributeToPropertyMap.set(attr, p); + attributes.push(attr); + } + }); + return attributes; + } + /** + * Creates a property accessor on the element prototype if one does not exist + * and stores a {@linkcode PropertyDeclaration} for the property with the + * given options. The property setter calls the property's `hasChanged` + * property option or uses a strict identity check to determine whether or not + * to request an update. + * + * This method may be overridden to customize properties; however, + * when doing so, it's important to call `super.createProperty` to ensure + * the property is setup correctly. This method calls + * `getPropertyDescriptor` internally to get a descriptor to install. + * To customize what properties do when they are get or set, override + * `getPropertyDescriptor`. To customize the options for a property, + * implement `createProperty` like this: + * + * ```ts + * static createProperty(name, options) { + * options = Object.assign(options, {myOption: true}); + * super.createProperty(name, options); + * } + * ``` + * + * @nocollapse + * @category properties + */ + static createProperty(name, options = defaultPropertyDeclaration) { + // if this is a state property, force the attribute to false. + if (options.state) { + // Cast as any since this is readonly. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + options.attribute = false; + } + // Note, since this can be called by the `@property` decorator which + // is called before `finalize`, we ensure finalization has been kicked off. + this.finalize(); + this.elementProperties.set(name, options); + // Do not generate an accessor if the prototype already has one, since + // it would be lost otherwise and that would never be the user's intention; + // Instead, we expect users to call `requestUpdate` themselves from + // user-defined accessors. Note that if the super has an accessor we will + // still overwrite it + if (!options.noAccessor && !this.prototype.hasOwnProperty(name)) { + const key = typeof name === 'symbol' ? Symbol() : `__${name}`; + const descriptor = this.getPropertyDescriptor(name, key, options); + if (descriptor !== undefined) { + Object.defineProperty(this.prototype, name, descriptor); + } + } + } + /** + * Returns a property descriptor to be defined on the given named property. + * If no descriptor is returned, the property will not become an accessor. + * For example, + * + * ```ts + * class MyElement extends LitElement { + * static getPropertyDescriptor(name, key, options) { + * const defaultDescriptor = + * super.getPropertyDescriptor(name, key, options); + * const setter = defaultDescriptor.set; + * return { + * get: defaultDescriptor.get, + * set(value) { + * setter.call(this, value); + * // custom action. + * }, + * configurable: true, + * enumerable: true + * } + * } + * } + * ``` + * + * @nocollapse + * @category properties + */ + static getPropertyDescriptor(name, key, options) { + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + get() { + return this[key]; + }, + set(value) { + const oldValue = this[name]; + this[key] = value; + this.requestUpdate(name, oldValue, options); + }, + configurable: true, + enumerable: true, + }; + } + /** + * Returns the property options associated with the given property. + * These options are defined with a `PropertyDeclaration` via the `properties` + * object or the `@property` decorator and are registered in + * `createProperty(...)`. + * + * Note, this method should be considered "final" and not overridden. To + * customize the options for a given property, override + * {@linkcode createProperty}. + * + * @nocollapse + * @final + * @category properties + */ + static getPropertyOptions(name) { + return this.elementProperties.get(name) || defaultPropertyDeclaration; + } + /** + * Creates property accessors for registered properties, sets up element + * styling, and ensures any superclasses are also finalized. Returns true if + * the element was finalized. + * @nocollapse + */ + static finalize() { + if (this.hasOwnProperty(finalized)) { + return false; + } + this[finalized] = true; + // finalize any superclasses + const superCtor = Object.getPrototypeOf(this); + superCtor.finalize(); + // Create own set of initializers for this class if any exist on the + // superclass and copy them down. Note, for a small perf boost, avoid + // creating initializers unless needed. + if (superCtor._initializers !== undefined) { + this._initializers = [...superCtor._initializers]; + } + this.elementProperties = new Map(superCtor.elementProperties); + // initialize Map populated in observedAttributes + this.__attributeToPropertyMap = new Map(); + // make any properties + // Note, only process "own" properties since this element will inherit + // any properties defined on the superClass, and finalization ensures + // the entire prototype chain is finalized. + if (this.hasOwnProperty(JSCompiler_renameProperty('properties'))) { + const props = this.properties; + // support symbols in properties (IE11 does not support this) + const propKeys = [ + ...Object.getOwnPropertyNames(props), + ...Object.getOwnPropertySymbols(props), + ]; + // This for/of is ok because propKeys is an array + for (const p of propKeys) { + // note, use of `any` is due to TypeScript lack of support for symbol in + // index types + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.createProperty(p, props[p]); + } + } + this.elementStyles = this.finalizeStyles(this.styles); + return true; + } + /** + * Takes the styles the user supplied via the `static styles` property and + * returns the array of styles to apply to the element. + * Override this method to integrate into a style management system. + * + * Styles are deduplicated preserving the _last_ instance in the list. This + * is a performance optimization to avoid duplicated styles that can occur + * especially when composing via subclassing. The last item is kept to try + * to preserve the cascade order with the assumption that it's most important + * that last added styles override previous styles. + * + * @nocollapse + * @category styles + */ + static finalizeStyles(styles) { + const elementStyles = []; + if (Array.isArray(styles)) { + // Dedupe the flattened array in reverse order to preserve the last items. + // Casting to Array<unknown> works around TS error that + // appears to come from trying to flatten a type CSSResultArray. + const set = new Set(styles.flat(Infinity).reverse()); + // Then preserve original order by adding the set items in reverse order. + for (const s of set) { + elementStyles.unshift(getCompatibleStyle(s)); + } + } + else if (styles !== undefined) { + elementStyles.push(getCompatibleStyle(styles)); + } + return elementStyles; + } + /** + * Returns the property name for the given attribute `name`. + * @nocollapse + */ + static __attributeNameForProperty(name, options) { + const attribute = options.attribute; + return attribute === false + ? undefined + : typeof attribute === 'string' + ? attribute + : typeof name === 'string' + ? name.toLowerCase() + : undefined; + } + /** + * Internal only override point for customizing work done when elements + * are constructed. + * + * @internal + */ + _initialize() { + var _a; + this.__updatePromise = new Promise((res) => (this.enableUpdating = res)); + this._$changedProperties = new Map(); + this.__saveInstanceProperties(); + // ensures first update will be caught by an early access of + // `updateComplete` + this.requestUpdate(); + (_a = this.constructor._initializers) === null || _a === void 0 ? void 0 : _a.forEach((i) => i(this)); + } + /** + * Registers a `ReactiveController` to participate in the element's reactive + * update cycle. The element automatically calls into any registered + * controllers during its lifecycle callbacks. + * + * If the element is connected when `addController()` is called, the + * controller's `hostConnected()` callback will be immediately called. + * @category controllers + */ + addController(controller) { + var _a, _b; + ((_a = this.__controllers) !== null && _a !== void 0 ? _a : (this.__controllers = [])).push(controller); + // If a controller is added after the element has been connected, + // call hostConnected. Note, re-using existence of `renderRoot` here + // (which is set in connectedCallback) to avoid the need to track a + // first connected state. + if (this.renderRoot !== undefined && this.isConnected) { + (_b = controller.hostConnected) === null || _b === void 0 ? void 0 : _b.call(controller); + } + } + /** + * Removes a `ReactiveController` from the element. + * @category controllers + */ + removeController(controller) { + var _a; + // Note, if the indexOf is -1, the >>> will flip the sign which makes the + // splice do nothing. + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.splice(this.__controllers.indexOf(controller) >>> 0, 1); + } + /** + * Fixes any properties set on the instance before upgrade time. + * Otherwise these would shadow the accessor and break these properties. + * The properties are stored in a Map which is played back after the + * constructor runs. Note, on very old versions of Safari (<=9) or Chrome + * (<=41), properties created for native platform properties like (`id` or + * `name`) may not have default values set in the element constructor. On + * these browsers native properties appear on instances and therefore their + * default value will overwrite any element default (e.g. if the element sets + * this.id = 'id' in the constructor, the 'id' will become '' since this is + * the native platform default). + */ + __saveInstanceProperties() { + // Use forEach so this works even if for/of loops are compiled to for loops + // expecting arrays + this.constructor.elementProperties.forEach((_v, p) => { + if (this.hasOwnProperty(p)) { + this.__instanceProperties.set(p, this[p]); + delete this[p]; + } + }); + } + /** + * Returns the node into which the element should render and by default + * creates and returns an open shadowRoot. Implement to customize where the + * element's DOM is rendered. For example, to render into the element's + * childNodes, return `this`. + * + * @return Returns a node into which to render. + * @category rendering + */ + createRenderRoot() { + var _a; + const renderRoot = (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this.attachShadow(this.constructor.shadowRootOptions); + adoptStyles(renderRoot, this.constructor.elementStyles); + return renderRoot; + } + /** + * On first connection, creates the element's renderRoot, sets up + * element styling, and enables updating. + * @category lifecycle + */ + connectedCallback() { + var _a; + // create renderRoot before first update. + if (this.renderRoot === undefined) { + this.renderRoot = this.createRenderRoot(); + } + this.enableUpdating(true); + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.forEach((c) => { var _a; return (_a = c.hostConnected) === null || _a === void 0 ? void 0 : _a.call(c); }); + } + /** + * Note, this method should be considered final and not overridden. It is + * overridden on the element instance with a function that triggers the first + * update. + * @category updates + */ + enableUpdating(_requestedUpdate) { } + /** + * Allows for `super.disconnectedCallback()` in extensions while + * reserving the possibility of making non-breaking feature additions + * when disconnecting at some point in the future. + * @category lifecycle + */ + disconnectedCallback() { + var _a; + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.forEach((c) => { var _a; return (_a = c.hostDisconnected) === null || _a === void 0 ? void 0 : _a.call(c); }); + } + /** + * Synchronizes property values when attributes change. + * + * Specifically, when an attribute is set, the corresponding property is set. + * You should rarely need to implement this callback. If this method is + * overridden, `super.attributeChangedCallback(name, _old, value)` must be + * called. + * + * See [using the lifecycle callbacks](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks) + * on MDN for more information about the `attributeChangedCallback`. + * @category attributes + */ + attributeChangedCallback(name, _old, value) { + this._$attributeToProperty(name, value); + } + __propertyToAttribute(name, value, options = defaultPropertyDeclaration) { + var _a; + const attr = this.constructor.__attributeNameForProperty(name, options); + if (attr !== undefined && options.reflect === true) { + const converter = ((_a = options.converter) === null || _a === void 0 ? void 0 : _a.toAttribute) !== + undefined + ? options.converter + : defaultConverter; + const attrValue = converter.toAttribute(value, options.type); + // Track if the property is being reflected to avoid + // setting the property again via `attributeChangedCallback`. Note: + // 1. this takes advantage of the fact that the callback is synchronous. + // 2. will behave incorrectly if multiple attributes are in the reaction + // stack at time of calling. However, since we process attributes + // in `update` this should not be possible (or an extreme corner case + // that we'd like to discover). + // mark state reflecting + this.__reflectingProperty = name; + if (attrValue == null) { + this.removeAttribute(attr); + } + else { + this.setAttribute(attr, attrValue); + } + // mark state not reflecting + this.__reflectingProperty = null; + } + } + /** @internal */ + _$attributeToProperty(name, value) { + var _a; + const ctor = this.constructor; + // Note, hint this as an `AttributeMap` so closure clearly understands + // the type; it has issues with tracking types through statics + const propName = ctor.__attributeToPropertyMap.get(name); + // Use tracking info to avoid reflecting a property value to an attribute + // if it was just set because the attribute changed. + if (propName !== undefined && this.__reflectingProperty !== propName) { + const options = ctor.getPropertyOptions(propName); + const converter = typeof options.converter === 'function' + ? { fromAttribute: options.converter } + : ((_a = options.converter) === null || _a === void 0 ? void 0 : _a.fromAttribute) !== undefined + ? options.converter + : defaultConverter; + // mark state reflecting + this.__reflectingProperty = propName; + this[propName] = converter.fromAttribute(value, options.type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ); + // mark state not reflecting + this.__reflectingProperty = null; + } + } + /** + * Requests an update which is processed asynchronously. This should be called + * when an element should update based on some state not triggered by setting + * a reactive property. In this case, pass no arguments. It should also be + * called when manually implementing a property setter. In this case, pass the + * property `name` and `oldValue` to ensure that any configured property + * options are honored. + * + * @param name name of requesting property + * @param oldValue old value of requesting property + * @param options property options to use instead of the previously + * configured options + * @category updates + */ + requestUpdate(name, oldValue, options) { + let shouldRequestUpdate = true; + // If we have a property key, perform property update steps. + if (name !== undefined) { + options = + options || + this.constructor.getPropertyOptions(name); + const hasChanged = options.hasChanged || notEqual; + if (hasChanged(this[name], oldValue)) { + if (!this._$changedProperties.has(name)) { + this._$changedProperties.set(name, oldValue); + } + // Add to reflecting properties set. + // Note, it's important that every change has a chance to add the + // property to `_reflectingProperties`. This ensures setting + // attribute + property reflects correctly. + if (options.reflect === true && this.__reflectingProperty !== name) { + if (this.__reflectingProperties === undefined) { + this.__reflectingProperties = new Map(); + } + this.__reflectingProperties.set(name, options); + } + } + else { + // Abort the request if the property should not be considered changed. + shouldRequestUpdate = false; + } + } + if (!this.isUpdatePending && shouldRequestUpdate) { + this.__updatePromise = this.__enqueueUpdate(); + } + // Note, since this no longer returns a promise, in dev mode we return a + // thenable which warns if it's called. + return undefined; + } + /** + * Sets up the element to asynchronously update. + */ + async __enqueueUpdate() { + this.isUpdatePending = true; + try { + // Ensure any previous update has resolved before updating. + // This `await` also ensures that property changes are batched. + await this.__updatePromise; + } + catch (e) { + // Refire any previous errors async so they do not disrupt the update + // cycle. Errors are refired so developers have a chance to observe + // them, and this can be done by implementing + // `window.onunhandledrejection`. + Promise.reject(e); + } + const result = this.scheduleUpdate(); + // If `scheduleUpdate` returns a Promise, we await it. This is done to + // enable coordinating updates with a scheduler. Note, the result is + // checked to avoid delaying an additional microtask unless we need to. + if (result != null) { + await result; + } + return !this.isUpdatePending; + } + /** + * Schedules an element update. You can override this method to change the + * timing of updates by returning a Promise. The update will await the + * returned Promise, and you should resolve the Promise to allow the update + * to proceed. If this method is overridden, `super.scheduleUpdate()` + * must be called. + * + * For instance, to schedule updates to occur just before the next frame: + * + * ```ts + * override protected async scheduleUpdate(): Promise<unknown> { + * await new Promise((resolve) => requestAnimationFrame(() => resolve())); + * super.scheduleUpdate(); + * } + * ``` + * @category updates + */ + scheduleUpdate() { + return this.performUpdate(); + } + /** + * Performs an element update. Note, if an exception is thrown during the + * update, `firstUpdated` and `updated` will not be called. + * + * Call `performUpdate()` to immediately process a pending update. This should + * generally not be needed, but it can be done in rare cases when you need to + * update synchronously. + * + * Note: To ensure `performUpdate()` synchronously completes a pending update, + * it should not be overridden. In LitElement 2.x it was suggested to override + * `performUpdate()` to also customizing update scheduling. Instead, you should now + * override `scheduleUpdate()`. For backwards compatibility with LitElement 2.x, + * scheduling updates via `performUpdate()` continues to work, but will make + * also calling `performUpdate()` to synchronously process updates difficult. + * + * @category updates + */ + performUpdate() { + var _b; + // Abort any update if one is not pending when this is called. + // This can happen if `performUpdate` is called early to "flush" + // the update. + if (!this.isUpdatePending) { + return; + } + // create renderRoot before first update. + if (!this.hasUpdated) ; + // Mixin instance properties once, if they exist. + if (this.__instanceProperties) { + // Use forEach so this works even if for/of loops are compiled to for loops + // expecting arrays + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.__instanceProperties.forEach((v, p) => (this[p] = v)); + this.__instanceProperties = undefined; + } + let shouldUpdate = false; + const changedProperties = this._$changedProperties; + try { + shouldUpdate = this.shouldUpdate(changedProperties); + if (shouldUpdate) { + this.willUpdate(changedProperties); + (_b = this.__controllers) === null || _b === void 0 ? void 0 : _b.forEach((c) => { var _a; return (_a = c.hostUpdate) === null || _a === void 0 ? void 0 : _a.call(c); }); + this.update(changedProperties); + } + else { + this.__markUpdated(); + } + } + catch (e) { + // Prevent `firstUpdated` and `updated` from running when there's an + // update exception. + shouldUpdate = false; + // Ensure element can accept additional updates after an exception. + this.__markUpdated(); + throw e; + } + // The update is no longer considered pending and further updates are now allowed. + if (shouldUpdate) { + this._$didUpdate(changedProperties); + } + } + /** + * Invoked before `update()` to compute values needed during the update. + * + * Implement `willUpdate` to compute property values that depend on other + * properties and are used in the rest of the update process. + * + * ```ts + * willUpdate(changedProperties) { + * // only need to check changed properties for an expensive computation. + * if (changedProperties.has('firstName') || changedProperties.has('lastName')) { + * this.sha = computeSHA(`${this.firstName} ${this.lastName}`); + * } + * } + * + * render() { + * return html`SHA: ${this.sha}`; + * } + * ``` + * + * @category updates + */ + willUpdate(_changedProperties) { } + // Note, this is an override point for polyfill-support. + // @internal + _$didUpdate(changedProperties) { + var _a; + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.forEach((c) => { var _a; return (_a = c.hostUpdated) === null || _a === void 0 ? void 0 : _a.call(c); }); + if (!this.hasUpdated) { + this.hasUpdated = true; + this.firstUpdated(changedProperties); + } + this.updated(changedProperties); + } + __markUpdated() { + this._$changedProperties = new Map(); + this.isUpdatePending = false; + } + /** + * Returns a Promise that resolves when the element has completed updating. + * The Promise value is a boolean that is `true` if the element completed the + * update without triggering another update. The Promise result is `false` if + * a property was set inside `updated()`. If the Promise is rejected, an + * exception was thrown during the update. + * + * To await additional asynchronous work, override the `getUpdateComplete` + * method. For example, it is sometimes useful to await a rendered element + * before fulfilling this Promise. To do this, first await + * `super.getUpdateComplete()`, then any subsequent state. + * + * @return A promise of a boolean that resolves to true if the update completed + * without triggering another update. + * @category updates + */ + get updateComplete() { + return this.getUpdateComplete(); + } + /** + * Override point for the `updateComplete` promise. + * + * It is not safe to override the `updateComplete` getter directly due to a + * limitation in TypeScript which means it is not possible to call a + * superclass getter (e.g. `super.updateComplete.then(...)`) when the target + * language is ES5 (https://github.com/microsoft/TypeScript/issues/338). + * This method should be overridden instead. For example: + * + * ```ts + * class MyElement extends LitElement { + * override async getUpdateComplete() { + * const result = await super.getUpdateComplete(); + * await this._myChild.updateComplete; + * return result; + * } + * } + * ``` + * + * @return A promise of a boolean that resolves to true if the update completed + * without triggering another update. + * @category updates + */ + getUpdateComplete() { + return this.__updatePromise; + } + /** + * Controls whether or not `update()` should be called when the element requests + * an update. By default, this method always returns `true`, but this can be + * customized to control when to update. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + shouldUpdate(_changedProperties) { + return true; + } + /** + * Updates the element. This method reflects property values to attributes. + * It can be overridden to render and keep updated element DOM. + * Setting properties inside this method will *not* trigger + * another update. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + update(_changedProperties) { + if (this.__reflectingProperties !== undefined) { + // Use forEach so this works even if for/of loops are compiled to for + // loops expecting arrays + this.__reflectingProperties.forEach((v, k) => this.__propertyToAttribute(k, this[k], v)); + this.__reflectingProperties = undefined; + } + this.__markUpdated(); + } + /** + * Invoked whenever the element is updated. Implement to perform + * post-updating tasks via DOM APIs, for example, focusing an element. + * + * Setting properties inside this method will trigger the element to update + * again after this update cycle completes. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + updated(_changedProperties) { } + /** + * Invoked when the element is first updated. Implement to perform one time + * work on the element after update. + * + * ```ts + * firstUpdated() { + * this.renderRoot.getElementById('my-text-area').focus(); + * } + * ``` + * + * Setting properties inside this method will trigger the element to update + * again after this update cycle completes. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + firstUpdated(_changedProperties) { } +} +_e = finalized; +/** + * Marks class as having finished creating properties. + */ +ReactiveElement[_e] = true; +/** + * Memoized list of all element properties, including any superclass properties. + * Created lazily on user subclasses when finalizing the class. + * @nocollapse + * @category properties + */ +ReactiveElement.elementProperties = new Map(); +/** + * Memoized list of all element styles. + * Created lazily on user subclasses when finalizing the class. + * @nocollapse + * @category styles + */ +ReactiveElement.elementStyles = []; +/** + * Options used when calling `attachShadow`. Set this property to customize + * the options for the shadowRoot; for example, to create a closed + * shadowRoot: `{mode: 'closed'}`. + * + * Note, these options are used in `createRenderRoot`. If this method + * is customized, options should be respected if possible. + * @nocollapse + * @category rendering + */ +ReactiveElement.shadowRootOptions = { mode: 'open' }; +// Apply polyfills if available +polyfillSupport$2 === null || polyfillSupport$2 === void 0 ? void 0 : polyfillSupport$2({ ReactiveElement }); +// IMPORTANT: do not change the property name or the assignment expression. +// This line will be used in regexes to search for ReactiveElement usage. +((_d$1 = global$1.reactiveElementVersions) !== null && _d$1 !== void 0 ? _d$1 : (global$1.reactiveElementVersions = [])).push('1.5.0'); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +var _d; +// Use window for browser builds because IE11 doesn't have globalThis. +const global = window; +const __moz_domParser = new DOMParser(); +const wrap$1 = (node) => node; +const trustedTypes = global.trustedTypes; +/** + * Our TrustedTypePolicy for HTML which is declared using the html template + * tag function. + * + * That HTML is a developer-authored constant, and is parsed with innerHTML + * before any untrusted expressions have been mixed in. Therefor it is + * considered safe by construction. + */ +const policy = trustedTypes + ? trustedTypes.createPolicy('lit-html', { + createHTML: (s) => s, + }) + : undefined; +// Added to an attribute name to mark the attribute as bound so we can find +// it easily. +const boundAttributeSuffix = '$lit$'; +// This marker is used in many syntactic positions in HTML, so it must be +// a valid element name and attribute name. We don't support dynamic names (yet) +// but this at least ensures that the parse tree is closer to the template +// intention. +const marker = `lit$${String(Math.random()).slice(9)}$`; +// String used to tell if a comment is a marker comment +const markerMatch = '?' + marker; +// Text used to insert a comment marker node. We use processing instruction +// syntax because it's slightly smaller, but parses as a comment node. +const nodeMarker = `<${markerMatch}>`; +const d = document; +// Creates a dynamic marker. We never have to search for these in the DOM. +const createMarker$1 = (v = '') => d.createComment(v); +const isPrimitive$1 = (value) => value === null || (typeof value != 'object' && typeof value != 'function'); +const isArray = Array.isArray; +const isIterable = (value) => isArray(value) || + // eslint-disable-next-line @typescript-eslint/no-explicit-any + typeof (value === null || value === void 0 ? void 0 : value[Symbol.iterator]) === 'function'; +const SPACE_CHAR = `[ \t\n\f\r]`; +const ATTR_VALUE_CHAR = `[^ \t\n\f\r"'\`<>=]`; +const NAME_CHAR = `[^\\s"'>=/]`; +// These regexes represent the five parsing states that we care about in the +// Template's HTML scanner. They match the *end* of the state they're named +// after. +// Depending on the match, we transition to a new state. If there's no match, +// we stay in the same state. +// Note that the regexes are stateful. We utilize lastIndex and sync it +// across the multiple regexes used. In addition to the five regexes below +// we also dynamically create a regex to find the matching end tags for raw +// text elements. +/** + * End of text is: `<` followed by: + * (comment start) or (tag) or (dynamic tag binding) + */ +const textEndRegex = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g; +const COMMENT_START = 1; +const TAG_NAME = 2; +const DYNAMIC_TAG_NAME = 3; +const commentEndRegex = /-->/g; +/** + * Comments not started with <!--, like </{, can be ended by a single `>` + */ +const comment2EndRegex = />/g; +/** + * The tagEnd regex matches the end of the "inside an opening" tag syntax + * position. It either matches a `>`, an attribute-like sequence, or the end + * of the string after a space (attribute-name position ending). + * + * See attributes in the HTML spec: + * https://www.w3.org/TR/html5/syntax.html#elements-attributes + * + * " \t\n\f\r" are HTML space characters: + * https://infra.spec.whatwg.org/#ascii-whitespace + * + * So an attribute is: + * * The name: any character except a whitespace character, ("), ('), ">", + * "=", or "/". Note: this is different from the HTML spec which also excludes control characters. + * * Followed by zero or more space characters + * * Followed by "=" + * * Followed by zero or more space characters + * * Followed by: + * * Any character except space, ('), ("), "<", ">", "=", (`), or + * * (") then any non-("), or + * * (') then any non-(') + */ +const tagEndRegex = new RegExp(`>|${SPACE_CHAR}(?:(${NAME_CHAR}+)(${SPACE_CHAR}*=${SPACE_CHAR}*(?:${ATTR_VALUE_CHAR}|("|')|))|$)`, 'g'); +const ENTIRE_MATCH = 0; +const ATTRIBUTE_NAME = 1; +const SPACES_AND_EQUALS = 2; +const QUOTE_CHAR = 3; +const singleQuoteAttrEndRegex = /'/g; +const doubleQuoteAttrEndRegex = /"/g; +/** + * Matches the raw text elements. + * + * Comments are not parsed within raw text elements, so we need to search their + * text content for marker strings. + */ +const rawTextElement = /^(?:script|style|textarea|title)$/i; +/** TemplateResult types */ +const HTML_RESULT$1 = 1; +const SVG_RESULT$1 = 2; +// TemplatePart types +// IMPORTANT: these must match the values in PartType +const ATTRIBUTE_PART = 1; +const CHILD_PART = 2; +const PROPERTY_PART = 3; +const BOOLEAN_ATTRIBUTE_PART = 4; +const EVENT_PART = 5; +const ELEMENT_PART = 6; +const COMMENT_PART = 7; +/** + * Generates a template literal tag function that returns a TemplateResult with + * the given result type. + */ +const tag = (type) => (strings, ...values) => { + return { + // This property needs to remain unminified. + ['_$litType$']: type, + strings, + values, + }; +}; +/** + * Interprets a template literal as an HTML template that can efficiently + * render to and update a container. + * + * ```ts + * const header = (title: string) => html`<h1>${title}</h1>`; + * ``` + * + * The `html` tag returns a description of the DOM to render as a value. It is + * lazy, meaning no work is done until the template is rendered. When rendering, + * if a template comes from the same expression as a previously rendered result, + * it's efficiently updated instead of replaced. + */ +const html$1 = tag(HTML_RESULT$1); +/** + * Interprets a template literal as an SVG fragment that can efficiently + * render to and update a container. + * + * ```ts + * const rect = svg`<rect width="10" height="10"></rect>`; + * + * const myImage = html` + * <svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"> + * ${rect} + * </svg>`; + * ``` + * + * The `svg` *tag function* should only be used for SVG fragments, or elements + * that would be contained **inside** an `<svg>` HTML element. A common error is + * placing an `<svg>` *element* in a template tagged with the `svg` tag + * function. The `<svg>` element is an HTML element and should be used within a + * template tagged with the {@linkcode html} tag function. + * + * In LitElement usage, it's invalid to return an SVG fragment from the + * `render()` method, as the SVG fragment will be contained within the element's + * shadow root and thus cannot be used within an `<svg>` HTML element. + */ +const svg$1 = tag(SVG_RESULT$1); +/** + * A sentinel value that signals that a value was handled by a directive and + * should not be written to the DOM. + */ +const noChange = Symbol.for('lit-noChange'); +/** + * A sentinel value that signals a ChildPart to fully clear its content. + * + * ```ts + * const button = html`${ + * user.isAdmin + * ? html`<button>DELETE</button>` + * : nothing + * }`; + * ``` + * + * Prefer using `nothing` over other falsy values as it provides a consistent + * behavior between various expression binding contexts. + * + * In child expressions, `undefined`, `null`, `''`, and `nothing` all behave the + * same and render no nodes. In attribute expressions, `nothing` _removes_ the + * attribute, while `undefined` and `null` will render an empty string. In + * property expressions `nothing` becomes `undefined`. + */ +const nothing = Symbol.for('lit-nothing'); +/** + * The cache of prepared templates, keyed by the tagged TemplateStringsArray + * and _not_ accounting for the specific template tag used. This means that + * template tags cannot be dynamic - the must statically be one of html, svg, + * or attr. This restriction simplifies the cache lookup, which is on the hot + * path for rendering. + */ +const templateCache = new WeakMap(); +const walker = d.createTreeWalker(d, 129 /* NodeFilter.SHOW_{ELEMENT|COMMENT} */, null, false); +/** + * Returns an HTML string for the given TemplateStringsArray and result type + * (HTML or SVG), along with the case-sensitive bound attribute names in + * template order. The HTML contains comment markers denoting the `ChildPart`s + * and suffixes on bound attributes denoting the `AttributeParts`. + * + * @param strings template strings array + * @param type HTML or SVG + * @return Array containing `[html, attrNames]` (array returned for terseness, + * to avoid object fields since this code is shared with non-minified SSR + * code) + */ +const getTemplateHtml = (strings, type) => { + // Insert makers into the template HTML to represent the position of + // bindings. The following code scans the template strings to determine the + // syntactic position of the bindings. They can be in text position, where + // we insert an HTML comment, attribute value position, where we insert a + // sentinel string and re-write the attribute name, or inside a tag where + // we insert the sentinel string. + const l = strings.length - 1; + // Stores the case-sensitive bound attribute names in the order of their + // parts. ElementParts are also reflected in this array as undefined + // rather than a string, to disambiguate from attribute bindings. + const attrNames = []; + let html = type === SVG_RESULT$1 ? '<svg>' : ''; + // When we're inside a raw text tag (not it's text content), the regex + // will still be tagRegex so we can find attributes, but will switch to + // this regex when the tag ends. + let rawTextEndRegex; + // The current parsing state, represented as a reference to one of the + // regexes + let regex = textEndRegex; + for (let i = 0; i < l; i++) { + const s = strings[i]; + // The index of the end of the last attribute name. When this is + // positive at end of a string, it means we're in an attribute value + // position and need to rewrite the attribute name. + // We also use a special value of -2 to indicate that we encountered + // the end of a string in attribute name position. + let attrNameEndIndex = -1; + let attrName; + let lastIndex = 0; + let match; + // The conditions in this loop handle the current parse state, and the + // assignments to the `regex` variable are the state transitions. + while (lastIndex < s.length) { + // Make sure we start searching from where we previously left off + regex.lastIndex = lastIndex; + match = regex.exec(s); + if (match === null) { + break; + } + lastIndex = regex.lastIndex; + if (regex === textEndRegex) { + if (match[COMMENT_START] === '!--') { + regex = commentEndRegex; + } + else if (match[COMMENT_START] !== undefined) { + // We started a weird comment, like </{ + regex = comment2EndRegex; + } + else if (match[TAG_NAME] !== undefined) { + if (rawTextElement.test(match[TAG_NAME])) { + // Record if we encounter a raw-text element. We'll switch to + // this regex at the end of the tag. + rawTextEndRegex = new RegExp(`</${match[TAG_NAME]}`, 'g'); + } + regex = tagEndRegex; + } + else if (match[DYNAMIC_TAG_NAME] !== undefined) { + regex = tagEndRegex; + } + } + else if (regex === tagEndRegex) { + if (match[ENTIRE_MATCH] === '>') { + // End of a tag. If we had started a raw-text element, use that + // regex + regex = rawTextEndRegex !== null && rawTextEndRegex !== void 0 ? rawTextEndRegex : textEndRegex; + // We may be ending an unquoted attribute value, so make sure we + // clear any pending attrNameEndIndex + attrNameEndIndex = -1; + } + else if (match[ATTRIBUTE_NAME] === undefined) { + // Attribute name position + attrNameEndIndex = -2; + } + else { + attrNameEndIndex = regex.lastIndex - match[SPACES_AND_EQUALS].length; + attrName = match[ATTRIBUTE_NAME]; + regex = + match[QUOTE_CHAR] === undefined + ? tagEndRegex + : match[QUOTE_CHAR] === '"' + ? doubleQuoteAttrEndRegex + : singleQuoteAttrEndRegex; + } + } + else if (regex === doubleQuoteAttrEndRegex || + regex === singleQuoteAttrEndRegex) { + regex = tagEndRegex; + } + else if (regex === commentEndRegex || regex === comment2EndRegex) { + regex = textEndRegex; + } + else { + // Not one of the five state regexes, so it must be the dynamically + // created raw text regex and we're at the close of that element. + regex = tagEndRegex; + rawTextEndRegex = undefined; + } + } + // We have four cases: + // 1. We're in text position, and not in a raw text element + // (regex === textEndRegex): insert a comment marker. + // 2. We have a non-negative attrNameEndIndex which means we need to + // rewrite the attribute name to add a bound attribute suffix. + // 3. We're at the non-first binding in a multi-binding attribute, use a + // plain marker. + // 4. We're somewhere else inside the tag. If we're in attribute name + // position (attrNameEndIndex === -2), add a sequential suffix to + // generate a unique attribute name. + // Detect a binding next to self-closing tag end and insert a space to + // separate the marker from the tag end: + const end = regex === tagEndRegex && strings[i + 1].startsWith('/>') ? ' ' : ''; + html += + regex === textEndRegex + ? s + nodeMarker + : attrNameEndIndex >= 0 + ? (attrNames.push(attrName), + s.slice(0, attrNameEndIndex) + + boundAttributeSuffix + + s.slice(attrNameEndIndex)) + + marker + + end + : s + + marker + + (attrNameEndIndex === -2 ? (attrNames.push(undefined), i) : end); + } + const htmlResult = html + (strings[l] || '<?>') + (type === SVG_RESULT$1 ? '</svg>' : ''); + // A security check to prevent spoofing of Lit template results. + // In the future, we may be able to replace this with Array.isTemplateObject, + // though we might need to make that check inside of the html and svg + // functions, because precompiled templates don't come in as + // TemplateStringArray objects. + if (!Array.isArray(strings) || !strings.hasOwnProperty('raw')) { + let message = 'invalid template strings array'; + throw new Error(message); + } + // Returned as an array for terseness + return [ + policy !== undefined + ? policy.createHTML(htmlResult) + : htmlResult, + attrNames, + ]; +}; +class Template { + constructor( + // This property needs to remain unminified. + { strings, ['_$litType$']: type }, options) { + /** @internal */ + this.parts = []; + let node; + let nodeIndex = 0; + let attrNameIndex = 0; + const partCount = strings.length - 1; + const parts = this.parts; + // Create template element + const [html, attrNames] = getTemplateHtml(strings, type); + this.el = Template.createElement(html, options); + walker.currentNode = this.el.content; + // Reparent SVG nodes into template root + if (type === SVG_RESULT$1) { + const content = this.el.content; + const svgElement = content.firstChild; + svgElement.remove(); + content.append(...svgElement.childNodes); + } + // Walk the template to find binding markers and create TemplateParts + while ((node = walker.nextNode()) !== null && parts.length < partCount) { + if (node.nodeType === 1) { + // TODO (justinfagnani): for attempted dynamic tag names, we don't + // increment the bindingIndex, and it'll be off by 1 in the element + // and off by two after it. + if (node.hasAttributes()) { + // We defer removing bound attributes because on IE we might not be + // iterating attributes in their template order, and would sometimes + // remove an attribute that we still need to create a part for. + const attrsToRemove = []; + for (const name of node.getAttributeNames()) { + // `name` is the name of the attribute we're iterating over, but not + // _neccessarily_ the name of the attribute we will create a part + // for. They can be different in browsers that don't iterate on + // attributes in source order. In that case the attrNames array + // contains the attribute name we'll process next. We only need the + // attribute name here to know if we should process a bound attribute + // on this element. + if (name.endsWith(boundAttributeSuffix) || + name.startsWith(marker)) { + const realName = attrNames[attrNameIndex++]; + attrsToRemove.push(name); + if (realName !== undefined) { + // Lowercase for case-sensitive SVG attributes like viewBox + const value = node.getAttribute(realName.toLowerCase() + boundAttributeSuffix); + const statics = value.split(marker); + const m = /([.?@])?(.*)/.exec(realName); + parts.push({ + type: ATTRIBUTE_PART, + index: nodeIndex, + name: m[2], + strings: statics, + ctor: m[1] === '.' + ? PropertyPart + : m[1] === '?' + ? BooleanAttributePart + : m[1] === '@' + ? EventPart + : AttributePart, + }); + } + else { + parts.push({ + type: ELEMENT_PART, + index: nodeIndex, + }); + } + } + } + for (const name of attrsToRemove) { + node.removeAttribute(name); + } + } + // TODO (justinfagnani): benchmark the regex against testing for each + // of the 3 raw text element names. + if (rawTextElement.test(node.tagName)) { + // For raw text elements we need to split the text content on + // markers, create a Text node for each segment, and create + // a TemplatePart for each marker. + const strings = node.textContent.split(marker); + const lastIndex = strings.length - 1; + if (lastIndex > 0) { + node.textContent = trustedTypes + ? trustedTypes.emptyScript + : ''; + // Generate a new text node for each literal section + // These nodes are also used as the markers for node parts + // We can't use empty text nodes as markers because they're + // normalized when cloning in IE (could simplify when + // IE is no longer supported) + for (let i = 0; i < lastIndex; i++) { + node.append(strings[i], createMarker$1()); + // Walk past the marker node we just added + walker.nextNode(); + parts.push({ type: CHILD_PART, index: ++nodeIndex }); + } + // Note because this marker is added after the walker's current + // node, it will be walked to in the outer loop (and ignored), so + // we don't need to adjust nodeIndex here + node.append(strings[lastIndex], createMarker$1()); + } + } + } + else if (node.nodeType === 8) { + const data = node.data; + if (data === markerMatch) { + parts.push({ type: CHILD_PART, index: nodeIndex }); + } + else { + let i = -1; + while ((i = node.data.indexOf(marker, i + 1)) !== -1) { + // Comment node has a binding marker inside, make an inactive part + // The binding won't work, but subsequent bindings will + parts.push({ type: COMMENT_PART, index: nodeIndex }); + // Move to the end of the match + i += marker.length - 1; + } + } + } + nodeIndex++; + } + } + // Overridden via `litHtmlPolyfillSupport` to provide platform support. + /** @nocollapse */ + static createElement(html, _options) { + const doc = __moz_domParser.parseFromString(`<template>${html}</template>`, 'text/html'); + return document.importNode(doc.querySelector('template'), true); + } +} +function resolveDirective(part, value, parent = part, attributeIndex) { + var _a, _b, _c; + var _d; + // Bail early if the value is explicitly noChange. Note, this means any + // nested directive is still attached and is not run. + if (value === noChange) { + return value; + } + let currentDirective = attributeIndex !== undefined + ? (_a = parent.__directives) === null || _a === void 0 ? void 0 : _a[attributeIndex] + : parent.__directive; + const nextDirectiveConstructor = isPrimitive$1(value) + ? undefined + : // This property needs to remain unminified. + value['_$litDirective$']; + if ((currentDirective === null || currentDirective === void 0 ? void 0 : currentDirective.constructor) !== nextDirectiveConstructor) { + // This property needs to remain unminified. + (_b = currentDirective === null || currentDirective === void 0 ? void 0 : currentDirective['_$notifyDirectiveConnectionChanged']) === null || _b === void 0 ? void 0 : _b.call(currentDirective, false); + if (nextDirectiveConstructor === undefined) { + currentDirective = undefined; + } + else { + currentDirective = new nextDirectiveConstructor(part); + currentDirective._$initialize(part, parent, attributeIndex); + } + if (attributeIndex !== undefined) { + ((_c = (_d = parent).__directives) !== null && _c !== void 0 ? _c : (_d.__directives = []))[attributeIndex] = + currentDirective; + } + else { + parent.__directive = currentDirective; + } + } + if (currentDirective !== undefined) { + value = resolveDirective(part, currentDirective._$resolve(part, value.values), currentDirective, attributeIndex); + } + return value; +} +/** + * An updateable instance of a Template. Holds references to the Parts used to + * update the template instance. + */ +class TemplateInstance { + constructor(template, parent) { + /** @internal */ + this._parts = []; + /** @internal */ + this._$disconnectableChildren = undefined; + this._$template = template; + this._$parent = parent; + } + // Called by ChildPart parentNode getter + get parentNode() { + return this._$parent.parentNode; + } + // See comment in Disconnectable interface for why this is a getter + get _$isConnected() { + return this._$parent._$isConnected; + } + // This method is separate from the constructor because we need to return a + // DocumentFragment and we don't want to hold onto it with an instance field. + _clone(options) { + var _a; + const { el: { content }, parts: parts, } = this._$template; + const fragment = ((_a = options === null || options === void 0 ? void 0 : options.creationScope) !== null && _a !== void 0 ? _a : d).importNode(content, true); + walker.currentNode = fragment; + let node = walker.nextNode(); + let nodeIndex = 0; + let partIndex = 0; + let templatePart = parts[0]; + while (templatePart !== undefined) { + if (nodeIndex === templatePart.index) { + let part; + if (templatePart.type === CHILD_PART) { + part = new ChildPart$1(node, node.nextSibling, this, options); + } + else if (templatePart.type === ATTRIBUTE_PART) { + part = new templatePart.ctor(node, templatePart.name, templatePart.strings, this, options); + } + else if (templatePart.type === ELEMENT_PART) { + part = new ElementPart(node, this, options); + } + this._parts.push(part); + templatePart = parts[++partIndex]; + } + if (nodeIndex !== (templatePart === null || templatePart === void 0 ? void 0 : templatePart.index)) { + node = walker.nextNode(); + nodeIndex++; + } + } + return fragment; + } + _update(values) { + let i = 0; + for (const part of this._parts) { + if (part !== undefined) { + if (part.strings !== undefined) { + part._$setValue(values, part, i); + // The number of values the part consumes is part.strings.length - 1 + // since values are in between template spans. We increment i by 1 + // later in the loop, so increment it by part.strings.length - 2 here + i += part.strings.length - 2; + } + else { + part._$setValue(values[i]); + } + } + i++; + } + } +} +class ChildPart$1 { + constructor(startNode, endNode, parent, options) { + var _a; + this.type = CHILD_PART; + this._$committedValue = nothing; + // The following fields will be patched onto ChildParts when required by + // AsyncDirective + /** @internal */ + this._$disconnectableChildren = undefined; + this._$startNode = startNode; + this._$endNode = endNode; + this._$parent = parent; + this.options = options; + // Note __isConnected is only ever accessed on RootParts (i.e. when there is + // no _$parent); the value on a non-root-part is "don't care", but checking + // for parent would be more code + this.__isConnected = (_a = options === null || options === void 0 ? void 0 : options.isConnected) !== null && _a !== void 0 ? _a : true; + } + // See comment in Disconnectable interface for why this is a getter + get _$isConnected() { + var _a, _b; + // ChildParts that are not at the root should always be created with a + // parent; only RootChildNode's won't, so they return the local isConnected + // state + return (_b = (_a = this._$parent) === null || _a === void 0 ? void 0 : _a._$isConnected) !== null && _b !== void 0 ? _b : this.__isConnected; + } + /** + * The parent node into which the part renders its content. + * + * A ChildPart's content consists of a range of adjacent child nodes of + * `.parentNode`, possibly bordered by 'marker nodes' (`.startNode` and + * `.endNode`). + * + * - If both `.startNode` and `.endNode` are non-null, then the part's content + * consists of all siblings between `.startNode` and `.endNode`, exclusively. + * + * - If `.startNode` is non-null but `.endNode` is null, then the part's + * content consists of all siblings following `.startNode`, up to and + * including the last child of `.parentNode`. If `.endNode` is non-null, then + * `.startNode` will always be non-null. + * + * - If both `.endNode` and `.startNode` are null, then the part's content + * consists of all child nodes of `.parentNode`. + */ + get parentNode() { + let parentNode = wrap$1(this._$startNode).parentNode; + const parent = this._$parent; + if (parent !== undefined && + parentNode.nodeType === 11 /* Node.DOCUMENT_FRAGMENT */) { + // If the parentNode is a DocumentFragment, it may be because the DOM is + // still in the cloned fragment during initial render; if so, get the real + // parentNode the part will be committed into by asking the parent. + parentNode = parent.parentNode; + } + return parentNode; + } + /** + * The part's leading marker node, if any. See `.parentNode` for more + * information. + */ + get startNode() { + return this._$startNode; + } + /** + * The part's trailing marker node, if any. See `.parentNode` for more + * information. + */ + get endNode() { + return this._$endNode; + } + _$setValue(value, directiveParent = this) { + value = resolveDirective(this, value, directiveParent); + if (isPrimitive$1(value)) { + // Non-rendering child values. It's important that these do not render + // empty text nodes to avoid issues with preventing default <slot> + // fallback content. + if (value === nothing || value == null || value === '') { + if (this._$committedValue !== nothing) { + this._$clear(); + } + this._$committedValue = nothing; + } + else if (value !== this._$committedValue && value !== noChange) { + this._commitText(value); + } + // This property needs to remain unminified. + } + else if (value['_$litType$'] !== undefined) { + this._commitTemplateResult(value); + } + else if (value.nodeType !== undefined) { + this._commitNode(value); + } + else if (isIterable(value)) { + this._commitIterable(value); + } + else { + // Fallback, will render the string representation + this._commitText(value); + } + } + _insert(node, ref = this._$endNode) { + return wrap$1(wrap$1(this._$startNode).parentNode).insertBefore(node, ref); + } + _commitNode(value) { + if (this._$committedValue !== value) { + this._$clear(); + this._$committedValue = this._insert(value); + } + } + _commitText(value) { + // If the committed value is a primitive it means we called _commitText on + // the previous render, and we know that this._$startNode.nextSibling is a + // Text node. We can now just replace the text content (.data) of the node. + if (this._$committedValue !== nothing && + isPrimitive$1(this._$committedValue)) { + const node = wrap$1(this._$startNode).nextSibling; + node.data = value; + } + else { + { + this._commitNode(d.createTextNode(value)); + } + } + this._$committedValue = value; + } + _commitTemplateResult(result) { + var _a; + // This property needs to remain unminified. + const { values, ['_$litType$']: type } = result; + // If $litType$ is a number, result is a plain TemplateResult and we get + // the template from the template cache. If not, result is a + // CompiledTemplateResult and _$litType$ is a CompiledTemplate and we need + // to create the <template> element the first time we see it. + const template = typeof type === 'number' + ? this._$getTemplate(result) + : (type.el === undefined && + (type.el = Template.createElement(type.h, this.options)), + type); + if (((_a = this._$committedValue) === null || _a === void 0 ? void 0 : _a._$template) === template) { + this._$committedValue._update(values); + } + else { + const instance = new TemplateInstance(template, this); + const fragment = instance._clone(this.options); + instance._update(values); + this._commitNode(fragment); + this._$committedValue = instance; + } + } + // Overridden via `litHtmlPolyfillSupport` to provide platform support. + /** @internal */ + _$getTemplate(result) { + let template = templateCache.get(result.strings); + if (template === undefined) { + templateCache.set(result.strings, (template = new Template(result))); + } + return template; + } + _commitIterable(value) { + // For an Iterable, we create a new InstancePart per item, then set its + // value to the item. This is a little bit of overhead for every item in + // an Iterable, but it lets us recurse easily and efficiently update Arrays + // of TemplateResults that will be commonly returned from expressions like: + // array.map((i) => html`${i}`), by reusing existing TemplateInstances. + // If value is an array, then the previous render was of an + // iterable and value will contain the ChildParts from the previous + // render. If value is not an array, clear this part and make a new + // array for ChildParts. + if (!isArray(this._$committedValue)) { + this._$committedValue = []; + this._$clear(); + } + // Lets us keep track of how many items we stamped so we can clear leftover + // items from a previous render + const itemParts = this._$committedValue; + let partIndex = 0; + let itemPart; + for (const item of value) { + if (partIndex === itemParts.length) { + // If no existing part, create a new one + // TODO (justinfagnani): test perf impact of always creating two parts + // instead of sharing parts between nodes + // https://github.com/lit/lit/issues/1266 + itemParts.push((itemPart = new ChildPart$1(this._insert(createMarker$1()), this._insert(createMarker$1()), this, this.options))); + } + else { + // Reuse an existing part + itemPart = itemParts[partIndex]; + } + itemPart._$setValue(item); + partIndex++; + } + if (partIndex < itemParts.length) { + // itemParts always have end nodes + this._$clear(itemPart && wrap$1(itemPart._$endNode).nextSibling, partIndex); + // Truncate the parts array so _value reflects the current state + itemParts.length = partIndex; + } + } + /** + * Removes the nodes contained within this Part from the DOM. + * + * @param start Start node to clear from, for clearing a subset of the part's + * DOM (used when truncating iterables) + * @param from When `start` is specified, the index within the iterable from + * which ChildParts are being removed, used for disconnecting directives in + * those Parts. + * + * @internal + */ + _$clear(start = wrap$1(this._$startNode).nextSibling, from) { + var _a; + (_a = this._$notifyConnectionChanged) === null || _a === void 0 ? void 0 : _a.call(this, false, true, from); + while (start && start !== this._$endNode) { + const n = wrap$1(start).nextSibling; + wrap$1(start).remove(); + start = n; + } + } + /** + * Implementation of RootPart's `isConnected`. Note that this metod + * should only be called on `RootPart`s (the `ChildPart` returned from a + * top-level `render()` call). It has no effect on non-root ChildParts. + * @param isConnected Whether to set + * @internal + */ + setConnected(isConnected) { + var _a; + if (this._$parent === undefined) { + this.__isConnected = isConnected; + (_a = this._$notifyConnectionChanged) === null || _a === void 0 ? void 0 : _a.call(this, isConnected); + } + } +} +class AttributePart { + constructor(element, name, strings, parent, options) { + this.type = ATTRIBUTE_PART; + /** @internal */ + this._$committedValue = nothing; + /** @internal */ + this._$disconnectableChildren = undefined; + this.element = element; + this.name = name; + this._$parent = parent; + this.options = options; + if (strings.length > 2 || strings[0] !== '' || strings[1] !== '') { + this._$committedValue = new Array(strings.length - 1).fill(new String()); + this.strings = strings; + } + else { + this._$committedValue = nothing; + } + } + get tagName() { + return this.element.tagName; + } + // See comment in Disconnectable interface for why this is a getter + get _$isConnected() { + return this._$parent._$isConnected; + } + /** + * Sets the value of this part by resolving the value from possibly multiple + * values and static strings and committing it to the DOM. + * If this part is single-valued, `this._strings` will be undefined, and the + * method will be called with a single value argument. If this part is + * multi-value, `this._strings` will be defined, and the method is called + * with the value array of the part's owning TemplateInstance, and an offset + * into the value array from which the values should be read. + * This method is overloaded this way to eliminate short-lived array slices + * of the template instance values, and allow a fast-path for single-valued + * parts. + * + * @param value The part value, or an array of values for multi-valued parts + * @param valueIndex the index to start reading values from. `undefined` for + * single-valued parts + * @param noCommit causes the part to not commit its value to the DOM. Used + * in hydration to prime attribute parts with their first-rendered value, + * but not set the attribute, and in SSR to no-op the DOM operation and + * capture the value for serialization. + * + * @internal + */ + _$setValue(value, directiveParent = this, valueIndex, noCommit) { + const strings = this.strings; + // Whether any of the values has changed, for dirty-checking + let change = false; + if (strings === undefined) { + // Single-value binding case + value = resolveDirective(this, value, directiveParent, 0); + change = + !isPrimitive$1(value) || + (value !== this._$committedValue && value !== noChange); + if (change) { + this._$committedValue = value; + } + } + else { + // Interpolation case + const values = value; + value = strings[0]; + let i, v; + for (i = 0; i < strings.length - 1; i++) { + v = resolveDirective(this, values[valueIndex + i], directiveParent, i); + if (v === noChange) { + // If the user-provided value is `noChange`, use the previous value + v = this._$committedValue[i]; + } + change || (change = !isPrimitive$1(v) || v !== this._$committedValue[i]); + if (v === nothing) { + value = nothing; + } + else if (value !== nothing) { + value += (v !== null && v !== void 0 ? v : '') + strings[i + 1]; + } + // We always record each value, even if one is `nothing`, for future + // change detection. + this._$committedValue[i] = v; + } + } + if (change && !noCommit) { + this._commitValue(value); + } + } + /** @internal */ + _commitValue(value) { + if (value === nothing) { + wrap$1(this.element).removeAttribute(this.name); + } + else { + wrap$1(this.element).setAttribute(this.name, (value !== null && value !== void 0 ? value : '')); + } + } +} +class PropertyPart extends AttributePart { + constructor() { + super(...arguments); + this.type = PROPERTY_PART; + } + /** @internal */ + _commitValue(value) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.element[this.name] = value === nothing ? undefined : value; + } +} +// Temporary workaround for https://crbug.com/993268 +// Currently, any attribute starting with "on" is considered to be a +// TrustedScript source. Such boolean attributes must be set to the equivalent +// trusted emptyScript value. +const emptyStringForBooleanAttribute = trustedTypes + ? trustedTypes.emptyScript + : ''; +class BooleanAttributePart extends AttributePart { + constructor() { + super(...arguments); + this.type = BOOLEAN_ATTRIBUTE_PART; + } + /** @internal */ + _commitValue(value) { + if (value && value !== nothing) { + wrap$1(this.element).setAttribute(this.name, emptyStringForBooleanAttribute); + } + else { + wrap$1(this.element).removeAttribute(this.name); + } + } +} +class EventPart extends AttributePart { + constructor(element, name, strings, parent, options) { + super(element, name, strings, parent, options); + this.type = EVENT_PART; + } + // EventPart does not use the base _$setValue/_resolveValue implementation + // since the dirty checking is more complex + /** @internal */ + _$setValue(newListener, directiveParent = this) { + var _a; + newListener = + (_a = resolveDirective(this, newListener, directiveParent, 0)) !== null && _a !== void 0 ? _a : nothing; + if (newListener === noChange) { + return; + } + const oldListener = this._$committedValue; + // If the new value is nothing or any options change we have to remove the + // part as a listener. + const shouldRemoveListener = (newListener === nothing && oldListener !== nothing) || + newListener.capture !== + oldListener.capture || + newListener.once !== + oldListener.once || + newListener.passive !== + oldListener.passive; + // If the new value is not nothing and we removed the listener, we have + // to add the part as a listener. + const shouldAddListener = newListener !== nothing && + (oldListener === nothing || shouldRemoveListener); + if (shouldRemoveListener) { + this.element.removeEventListener(this.name, this, oldListener); + } + if (shouldAddListener) { + // Beware: IE11 and Chrome 41 don't like using the listener as the + // options object. Figure out how to deal w/ this in IE11 - maybe + // patch addEventListener? + this.element.addEventListener(this.name, this, newListener); + } + this._$committedValue = newListener; + } + handleEvent(event) { + var _a, _b; + if (typeof this._$committedValue === 'function') { + this._$committedValue.call((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.host) !== null && _b !== void 0 ? _b : this.element, event); + } + else { + this._$committedValue.handleEvent(event); + } + } +} +class ElementPart { + constructor(element, parent, options) { + this.element = element; + this.type = ELEMENT_PART; + /** @internal */ + this._$disconnectableChildren = undefined; + this._$parent = parent; + this.options = options; + } + // See comment in Disconnectable interface for why this is a getter + get _$isConnected() { + return this._$parent._$isConnected; + } + _$setValue(value) { + resolveDirective(this, value); + } +} +/** + * END USERS SHOULD NOT RELY ON THIS OBJECT. + * + * Private exports for use by other Lit packages, not intended for use by + * external users. + * + * We currently do not make a mangled rollup build of the lit-ssr code. In order + * to keep a number of (otherwise private) top-level exports mangled in the + * client side code, we export a _$LH object containing those members (or + * helper methods for accessing private fields of those members), and then + * re-export them for use in lit-ssr. This keeps lit-ssr agnostic to whether the + * client-side code is being used in `dev` mode or `prod` mode. + * + * This has a unique name, to disambiguate it from private exports in + * lit-element, which re-exports all of lit-html. + * + * @private + */ +const _$LH = { + // Used in lit-ssr + _boundAttributeSuffix: boundAttributeSuffix, + _marker: marker, + _markerMatch: markerMatch, + _HTML_RESULT: HTML_RESULT$1, + _getTemplateHtml: getTemplateHtml, + // Used in hydrate + _TemplateInstance: TemplateInstance, + _isIterable: isIterable, + _resolveDirective: resolveDirective, + // Used in tests and private-ssr-support + _ChildPart: ChildPart$1, + _AttributePart: AttributePart, + _BooleanAttributePart: BooleanAttributePart, + _EventPart: EventPart, + _PropertyPart: PropertyPart, + _ElementPart: ElementPart, +}; +// Apply polyfills if available +const polyfillSupport$1 = global.litHtmlPolyfillSupport; +polyfillSupport$1 === null || polyfillSupport$1 === void 0 ? void 0 : polyfillSupport$1(Template, ChildPart$1); +// IMPORTANT: do not change the property name or the assignment expression. +// This line will be used in regexes to search for lit-html usage. +((_d = global.litHtmlVersions) !== null && _d !== void 0 ? _d : (global.litHtmlVersions = [])).push('2.5.0'); +/** + * Renders a value, usually a lit-html TemplateResult, to the container. + * + * This example renders the text "Hello, Zoe!" inside a paragraph tag, appending + * it to the container `document.body`. + * + * ```js + * import {html, render} from 'lit'; + * + * const name = "Zoe"; + * render(html`<p>Hello, ${name}!</p>`, document.body); + * ``` + * + * @param value Any [renderable + * value](https://lit.dev/docs/templates/expressions/#child-expressions), + * typically a {@linkcode TemplateResult} created by evaluating a template tag + * like {@linkcode html} or {@linkcode svg}. + * @param container A DOM container to render to. The first render will append + * the rendered value to the container, and subsequent renders will + * efficiently update the rendered value if the same result type was + * previously rendered there. + * @param options See {@linkcode RenderOptions} for options documentation. + * @see + * {@link https://lit.dev/docs/libraries/standalone-templates/#rendering-lit-html-templates| Rendering Lit HTML Templates} + */ +const render = (value, container, options) => { + var _a, _b; + const partOwnerNode = (_a = options === null || options === void 0 ? void 0 : options.renderBefore) !== null && _a !== void 0 ? _a : container; + // This property needs to remain unminified. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let part = partOwnerNode['_$litPart$']; + if (part === undefined) { + const endNode = (_b = options === null || options === void 0 ? void 0 : options.renderBefore) !== null && _b !== void 0 ? _b : null; + // This property needs to remain unminified. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + partOwnerNode['_$litPart$'] = part = new ChildPart$1(container.insertBefore(createMarker$1(), endNode), endNode, undefined, options !== null && options !== void 0 ? options : {}); + } + part._$setValue(value); + return part; +}; + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +var _b, _c; +// For backwards compatibility export ReactiveElement as UpdatingElement. Note, +// IE transpilation requires exporting like this. +const UpdatingElement = ReactiveElement; +/** + * Base element class that manages element properties and attributes, and + * renders a lit-html template. + * + * To define a component, subclass `LitElement` and implement a + * `render` method to provide the component's template. Define properties + * using the {@linkcode LitElement.properties properties} property or the + * {@linkcode property} decorator. + */ +class LitElement extends ReactiveElement { + constructor() { + super(...arguments); + /** + * @category rendering + */ + this.renderOptions = { host: this }; + this.__childPart = undefined; + } + /** + * @category rendering + */ + createRenderRoot() { + var _a; + var _b; + const renderRoot = super.createRenderRoot(); + // When adoptedStyleSheets are shimmed, they are inserted into the + // shadowRoot by createRenderRoot. Adjust the renderBefore node so that + // any styles in Lit content render before adoptedStyleSheets. This is + // important so that adoptedStyleSheets have precedence over styles in + // the shadowRoot. + (_a = (_b = this.renderOptions).renderBefore) !== null && _a !== void 0 ? _a : (_b.renderBefore = renderRoot.firstChild); + return renderRoot; + } + /** + * Updates the element. This method reflects property values to attributes + * and calls `render` to render DOM via lit-html. Setting properties inside + * this method will *not* trigger another update. + * @param changedProperties Map of changed properties with old values + * @category updates + */ + update(changedProperties) { + // Setting properties in `render` should not trigger an update. Since + // updates are allowed after super.update, it's important to call `render` + // before that. + const value = this.render(); + if (!this.hasUpdated) { + this.renderOptions.isConnected = this.isConnected; + } + super.update(changedProperties); + this.__childPart = render(value, this.renderRoot, this.renderOptions); + } + /** + * Invoked when the component is added to the document's DOM. + * + * In `connectedCallback()` you should setup tasks that should only occur when + * the element is connected to the document. The most common of these is + * adding event listeners to nodes external to the element, like a keydown + * event handler added to the window. + * + * ```ts + * connectedCallback() { + * super.connectedCallback(); + * addEventListener('keydown', this._handleKeydown); + * } + * ``` + * + * Typically, anything done in `connectedCallback()` should be undone when the + * element is disconnected, in `disconnectedCallback()`. + * + * @category lifecycle + */ + connectedCallback() { + var _a; + super.connectedCallback(); + (_a = this.__childPart) === null || _a === void 0 ? void 0 : _a.setConnected(true); + } + /** + * Invoked when the component is removed from the document's DOM. + * + * This callback is the main signal to the element that it may no longer be + * used. `disconnectedCallback()` should ensure that nothing is holding a + * reference to the element (such as event listeners added to nodes external + * to the element), so that it is free to be garbage collected. + * + * ```ts + * disconnectedCallback() { + * super.disconnectedCallback(); + * window.removeEventListener('keydown', this._handleKeydown); + * } + * ``` + * + * An element may be re-connected after being disconnected. + * + * @category lifecycle + */ + disconnectedCallback() { + var _a; + super.disconnectedCallback(); + (_a = this.__childPart) === null || _a === void 0 ? void 0 : _a.setConnected(false); + } + /** + * Invoked on each update to perform rendering tasks. This method may return + * any value renderable by lit-html's `ChildPart` - typically a + * `TemplateResult`. Setting properties inside this method will *not* trigger + * the element to update. + * @category rendering + */ + render() { + return noChange; + } +} +/** + * Ensure this class is marked as `finalized` as an optimization ensuring + * it will not needlessly try to `finalize`. + * + * Note this property name is a string to prevent breaking Closure JS Compiler + * optimizations. See @lit/reactive-element for more information. + */ +LitElement['finalized'] = true; +// This property needs to remain unminified. +LitElement['_$litElement$'] = true; +// Install hydration if available +(_b = globalThis.litElementHydrateSupport) === null || _b === void 0 ? void 0 : _b.call(globalThis, { LitElement }); +// Apply polyfills if available +const polyfillSupport = globalThis.litElementPolyfillSupport; +polyfillSupport === null || polyfillSupport === void 0 ? void 0 : polyfillSupport({ LitElement }); +/** + * END USERS SHOULD NOT RELY ON THIS OBJECT. + * + * Private exports for use by other Lit packages, not intended for use by + * external users. + * + * We currently do not make a mangled rollup build of the lit-ssr code. In order + * to keep a number of (otherwise private) top-level exports mangled in the + * client side code, we export a _$LE object containing those members (or + * helper methods for accessing private fields of those members), and then + * re-export them for use in lit-ssr. This keeps lit-ssr agnostic to whether the + * client-side code is being used in `dev` mode or `prod` mode. + * + * This has a unique name, to disambiguate it from private exports in + * lit-html, since this module re-exports all of lit-html. + * + * @private + */ +const _$LE = { + _$attributeToProperty: (el, name, value) => { + // eslint-disable-next-line + el._$attributeToProperty(name, value); + }, + // eslint-disable-next-line + _$changedProperties: (el) => el._$changedProperties, +}; +// IMPORTANT: do not change the property name or the assignment expression. +// This line will be used in regexes to search for LitElement usage. +((_c = globalThis.litElementVersions) !== null && _c !== void 0 ? _c : (globalThis.litElementVersions = [])).push('3.2.2'); + +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +/** + * @fileoverview + * + * This file exports a boolean const whose value will depend on what environment + * the module is being imported from. + */ +const NODE_MODE = false; +/** + * A boolean that will be `true` in server environments like Node, and `false` + * in browser environments. Note that your server environment or toolchain must + * support the `"node"` export condition for this to be `true`. + * + * This can be used when authoring components to change behavior based on + * whether or not the component is executing in an SSR context. + */ +const isServer = NODE_MODE; + +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const { _ChildPart: ChildPart } = _$LH; +const wrap = (node) => node; +/** + * Tests if a value is a primitive value. + * + * See https://tc39.github.io/ecma262/#sec-typeof-operator + */ +const isPrimitive = (value) => value === null || (typeof value != 'object' && typeof value != 'function'); +const TemplateResultType = { + HTML: 1, + SVG: 2, +}; +/** + * Tests if a value is a TemplateResult. + */ +const isTemplateResult = (value, type) => type === undefined + ? // This property needs to remain unminified. + (value === null || value === void 0 ? void 0 : value['_$litType$']) !== undefined + : (value === null || value === void 0 ? void 0 : value['_$litType$']) === type; +/** + * Tests if a value is a DirectiveResult. + */ +const isDirectiveResult = (value) => +// This property needs to remain unminified. +(value === null || value === void 0 ? void 0 : value['_$litDirective$']) !== undefined; +/** + * Retrieves the Directive class for a DirectiveResult + */ +const getDirectiveClass = (value) => +// This property needs to remain unminified. +value === null || value === void 0 ? void 0 : value['_$litDirective$']; +/** + * Tests whether a part has only a single-expression with no strings to + * interpolate between. + * + * Only AttributePart and PropertyPart can have multiple expressions. + * Multi-expression parts have a `strings` property and single-expression + * parts do not. + */ +const isSingleExpression = (part) => part.strings === undefined; +const createMarker = () => document.createComment(''); +/** + * Inserts a ChildPart into the given container ChildPart's DOM, either at the + * end of the container ChildPart, or before the optional `refPart`. + * + * This does not add the part to the containerPart's committed value. That must + * be done by callers. + * + * @param containerPart Part within which to add the new ChildPart + * @param refPart Part before which to add the new ChildPart; when omitted the + * part added to the end of the `containerPart` + * @param part Part to insert, or undefined to create a new part + */ +const insertPart = (containerPart, refPart, part) => { + var _a; + const container = wrap(containerPart._$startNode).parentNode; + const refNode = refPart === undefined ? containerPart._$endNode : refPart._$startNode; + if (part === undefined) { + const startNode = wrap(container).insertBefore(createMarker(), refNode); + const endNode = wrap(container).insertBefore(createMarker(), refNode); + part = new ChildPart(startNode, endNode, containerPart, containerPart.options); + } + else { + const endNode = wrap(part._$endNode).nextSibling; + const oldParent = part._$parent; + const parentChanged = oldParent !== containerPart; + if (parentChanged) { + (_a = part._$reparentDisconnectables) === null || _a === void 0 ? void 0 : _a.call(part, containerPart); + // Note that although `_$reparentDisconnectables` updates the part's + // `_$parent` reference after unlinking from its current parent, that + // method only exists if Disconnectables are present, so we need to + // unconditionally set it here + part._$parent = containerPart; + // Since the _$isConnected getter is somewhat costly, only + // read it once we know the subtree has directives that need + // to be notified + let newConnectionState; + if (part._$notifyConnectionChanged !== undefined && + (newConnectionState = containerPart._$isConnected) !== + oldParent._$isConnected) { + part._$notifyConnectionChanged(newConnectionState); + } + } + if (endNode !== refNode || parentChanged) { + let start = part._$startNode; + while (start !== endNode) { + const n = wrap(start).nextSibling; + wrap(container).insertBefore(start, refNode); + start = n; + } + } + } + return part; +}; +/** + * Sets the value of a Part. + * + * Note that this should only be used to set/update the value of user-created + * parts (i.e. those created using `insertPart`); it should not be used + * by directives to set the value of the directive's container part. Directives + * should return a value from `update`/`render` to update their part state. + * + * For directives that require setting their part value asynchronously, they + * should extend `AsyncDirective` and call `this.setValue()`. + * + * @param part Part to set + * @param value Value to set + * @param index For `AttributePart`s, the index to set + * @param directiveParent Used internally; should not be set by user + */ +const setChildPartValue = (part, value, directiveParent = part) => { + part._$setValue(value, directiveParent); + return part; +}; +// A sentinal value that can never appear as a part value except when set by +// live(). Used to force a dirty-check to fail and cause a re-render. +const RESET_VALUE = {}; +/** + * Sets the committed value of a ChildPart directly without triggering the + * commit stage of the part. + * + * This is useful in cases where a directive needs to update the part such + * that the next update detects a value change or not. When value is omitted, + * the next update will be guaranteed to be detected as a change. + * + * @param part + * @param value + */ +const setCommittedValue = (part, value = RESET_VALUE) => (part._$committedValue = value); +/** + * Returns the committed value of a ChildPart. + * + * The committed value is used for change detection and efficient updates of + * the part. It can differ from the value set by the template or directive in + * cases where the template value is transformed before being commited. + * + * - `TemplateResult`s are committed as a `TemplateInstance` + * - Iterables are committed as `Array<ChildPart>` + * - All other types are committed as the template value or value returned or + * set by a directive. + * + * @param part + */ +const getCommittedValue = (part) => part._$committedValue; +/** + * Removes a ChildPart from the DOM, including any of its content. + * + * @param part The Part to remove + */ +const removePart = (part) => { + var _a; + (_a = part._$notifyConnectionChanged) === null || _a === void 0 ? void 0 : _a.call(part, false, true); + let start = part._$startNode; + const end = wrap(part._$endNode).nextSibling; + while (start !== end) { + const n = wrap(start).nextSibling; + wrap(start).remove(); + start = n; + } +}; +const clearPart = (part) => { + part._$clear(); +}; + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const PartType = { + ATTRIBUTE: 1, + CHILD: 2, + PROPERTY: 3, + BOOLEAN_ATTRIBUTE: 4, + EVENT: 5, + ELEMENT: 6, +}; +/** + * Creates a user-facing directive function from a Directive class. This + * function has the same parameters as the directive's render() method. + */ +const directive = (c) => (...values) => ({ + // This property needs to remain unminified. + ['_$litDirective$']: c, + values, +}); +/** + * Base class for creating custom directives. Users should extend this class, + * implement `render` and/or `update`, and then pass their subclass to + * `directive`. + */ +class Directive { + constructor(_partInfo) { } + // See comment in Disconnectable interface for why this is a getter + get _$isConnected() { + return this._$parent._$isConnected; + } + /** @internal */ + _$initialize(part, parent, attributeIndex) { + this.__part = part; + this._$parent = parent; + this.__attributeIndex = attributeIndex; + } + /** @internal */ + _$resolve(part, props) { + return this.update(part, props); + } + update(_part, props) { + return this.render(...props); + } +} + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +/** + * Recursively walks down the tree of Parts/TemplateInstances/Directives to set + * the connected state of directives and run `disconnected`/ `reconnected` + * callbacks. + * + * @return True if there were children to disconnect; false otherwise + */ +const notifyChildrenConnectedChanged = (parent, isConnected) => { + var _a, _b; + const children = parent._$disconnectableChildren; + if (children === undefined) { + return false; + } + for (const obj of children) { + // The existence of `_$notifyDirectiveConnectionChanged` is used as a "brand" to + // disambiguate AsyncDirectives from other DisconnectableChildren + // (as opposed to using an instanceof check to know when to call it); the + // redundancy of "Directive" in the API name is to avoid conflicting with + // `_$notifyConnectionChanged`, which exists `ChildParts` which are also in + // this list + // Disconnect Directive (and any nested directives contained within) + // This property needs to remain unminified. + (_b = (_a = obj)['_$notifyDirectiveConnectionChanged']) === null || _b === void 0 ? void 0 : _b.call(_a, isConnected, false); + // Disconnect Part/TemplateInstance + notifyChildrenConnectedChanged(obj, isConnected); + } + return true; +}; +/** + * Removes the given child from its parent list of disconnectable children, and + * if the parent list becomes empty as a result, removes the parent from its + * parent, and so forth up the tree when that causes subsequent parent lists to + * become empty. + */ +const removeDisconnectableFromParent = (obj) => { + let parent, children; + do { + if ((parent = obj._$parent) === undefined) { + break; + } + children = parent._$disconnectableChildren; + children.delete(obj); + obj = parent; + } while ((children === null || children === void 0 ? void 0 : children.size) === 0); +}; +const addDisconnectableToParent = (obj) => { + // Climb the parent tree, creating a sparse tree of children needing + // disconnection + for (let parent; (parent = obj._$parent); obj = parent) { + let children = parent._$disconnectableChildren; + if (children === undefined) { + parent._$disconnectableChildren = children = new Set(); + } + else if (children.has(obj)) { + // Once we've reached a parent that already contains this child, we + // can short-circuit + break; + } + children.add(obj); + installDisconnectAPI(parent); + } +}; +/** + * Changes the parent reference of the ChildPart, and updates the sparse tree of + * Disconnectable children accordingly. + * + * Note, this method will be patched onto ChildPart instances and called from + * the core code when parts are moved between different parents. + */ +function reparentDisconnectables(newParent) { + if (this._$disconnectableChildren !== undefined) { + removeDisconnectableFromParent(this); + this._$parent = newParent; + addDisconnectableToParent(this); + } + else { + this._$parent = newParent; + } +} +/** + * Sets the connected state on any directives contained within the committed + * value of this part (i.e. within a TemplateInstance or iterable of + * ChildParts) and runs their `disconnected`/`reconnected`s, as well as within + * any directives stored on the ChildPart (when `valueOnly` is false). + * + * `isClearingValue` should be passed as `true` on a top-level part that is + * clearing itself, and not as a result of recursively disconnecting directives + * as part of a `clear` operation higher up the tree. This both ensures that any + * directive on this ChildPart that produced a value that caused the clear + * operation is not disconnected, and also serves as a performance optimization + * to avoid needless bookkeeping when a subtree is going away; when clearing a + * subtree, only the top-most part need to remove itself from the parent. + * + * `fromPartIndex` is passed only in the case of a partial `_clear` running as a + * result of truncating an iterable. + * + * Note, this method will be patched onto ChildPart instances and called from the + * core code when parts are cleared or the connection state is changed by the + * user. + */ +function notifyChildPartConnectedChanged(isConnected, isClearingValue = false, fromPartIndex = 0) { + const value = this._$committedValue; + const children = this._$disconnectableChildren; + if (children === undefined || children.size === 0) { + return; + } + if (isClearingValue) { + if (Array.isArray(value)) { + // Iterable case: Any ChildParts created by the iterable should be + // disconnected and removed from this ChildPart's disconnectable + // children (starting at `fromPartIndex` in the case of truncation) + for (let i = fromPartIndex; i < value.length; i++) { + notifyChildrenConnectedChanged(value[i], false); + removeDisconnectableFromParent(value[i]); + } + } + else if (value != null) { + // TemplateInstance case: If the value has disconnectable children (will + // only be in the case that it is a TemplateInstance), we disconnect it + // and remove it from this ChildPart's disconnectable children + notifyChildrenConnectedChanged(value, false); + removeDisconnectableFromParent(value); + } + } + else { + notifyChildrenConnectedChanged(this, isConnected); + } +} +/** + * Patches disconnection API onto ChildParts. + */ +const installDisconnectAPI = (obj) => { + var _a, _b; + var _c, _d; + if (obj.type == PartType.CHILD) { + (_a = (_c = obj)._$notifyConnectionChanged) !== null && _a !== void 0 ? _a : (_c._$notifyConnectionChanged = notifyChildPartConnectedChanged); + (_b = (_d = obj)._$reparentDisconnectables) !== null && _b !== void 0 ? _b : (_d._$reparentDisconnectables = reparentDisconnectables); + } +}; +/** + * An abstract `Directive` base class whose `disconnected` method will be + * called when the part containing the directive is cleared as a result of + * re-rendering, or when the user calls `part.setConnected(false)` on + * a part that was previously rendered containing the directive (as happens + * when e.g. a LitElement disconnects from the DOM). + * + * If `part.setConnected(true)` is subsequently called on a + * containing part, the directive's `reconnected` method will be called prior + * to its next `update`/`render` callbacks. When implementing `disconnected`, + * `reconnected` should also be implemented to be compatible with reconnection. + * + * Note that updates may occur while the directive is disconnected. As such, + * directives should generally check the `this.isConnected` flag during + * render/update to determine whether it is safe to subscribe to resources + * that may prevent garbage collection. + */ +class AsyncDirective extends Directive { + constructor() { + super(...arguments); + // @internal + this._$disconnectableChildren = undefined; + } + /** + * Initialize the part with internal fields + * @param part + * @param parent + * @param attributeIndex + */ + _$initialize(part, parent, attributeIndex) { + super._$initialize(part, parent, attributeIndex); + addDisconnectableToParent(this); + this.isConnected = part._$isConnected; + } + // This property needs to remain unminified. + /** + * Called from the core code when a directive is going away from a part (in + * which case `shouldRemoveFromParent` should be true), and from the + * `setChildrenConnected` helper function when recursively changing the + * connection state of a tree (in which case `shouldRemoveFromParent` should + * be false). + * + * @param isConnected + * @param isClearingDirective - True when the directive itself is being + * removed; false when the tree is being disconnected + * @internal + */ + ['_$notifyDirectiveConnectionChanged'](isConnected, isClearingDirective = true) { + var _a, _b; + if (isConnected !== this.isConnected) { + this.isConnected = isConnected; + if (isConnected) { + (_a = this.reconnected) === null || _a === void 0 ? void 0 : _a.call(this); + } + else { + (_b = this.disconnected) === null || _b === void 0 ? void 0 : _b.call(this); + } + } + if (isClearingDirective) { + notifyChildrenConnectedChanged(this, isConnected); + removeDisconnectableFromParent(this); + } + } + /** + * Sets the value of the directive's Part outside the normal `update`/`render` + * lifecycle of a directive. + * + * This method should not be called synchronously from a directive's `update` + * or `render`. + * + * @param directive The directive to update + * @param value The value to set + */ + setValue(value) { + if (isSingleExpression(this.__part)) { + this.__part._$setValue(value, this); + } + else { + const newValues = [...this.__part._$committedValue]; + newValues[this.__attributeIndex] = value; + this.__part._$setValue(newValues, this, 0); + } + } + /** + * User callbacks for implementing logic to release any resources/subscriptions + * that may have been retained by this directive. Since directives may also be + * re-connected, `reconnected` should also be implemented to restore the + * working state of the directive prior to the next render. + */ + disconnected() { } + reconnected() { } +} + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +// Note, this module is not included in package exports so that it's private to +// our first-party directives. If it ends up being useful, we can open it up and +// export it. +/** + * Helper to iterate an AsyncIterable in its own closure. + * @param iterable The iterable to iterate + * @param callback The callback to call for each value. If the callback returns + * `false`, the loop will be broken. + */ +const forAwaitOf = async (iterable, callback) => { + for await (const v of iterable) { + if ((await callback(v)) === false) { + return; + } + } +}; +/** + * Holds a reference to an instance that can be disconnected and reconnected, + * so that a closure over the ref (e.g. in a then function to a promise) does + * not strongly hold a ref to the instance. Approximates a WeakRef but must + * be manually connected & disconnected to the backing instance. + */ +class PseudoWeakRef { + constructor(ref) { + this._ref = ref; + } + /** + * Disassociates the ref with the backing instance. + */ + disconnect() { + this._ref = undefined; + } + /** + * Reassociates the ref with the backing instance. + */ + reconnect(ref) { + this._ref = ref; + } + /** + * Retrieves the backing instance (will be undefined when disconnected) + */ + deref() { + return this._ref; + } +} +/** + * A helper to pause and resume waiting on a condition in an async function + */ +class Pauser { + constructor() { + this._promise = undefined; + this._resolve = undefined; + } + /** + * When paused, returns a promise to be awaited; when unpaused, returns + * undefined. Note that in the microtask between the pauser being resumed + * an an await of this promise resolving, the pauser could be paused again, + * hence callers should check the promise in a loop when awaiting. + * @returns A promise to be awaited when paused or undefined + */ + get() { + return this._promise; + } + /** + * Creates a promise to be awaited + */ + pause() { + var _a; + (_a = this._promise) !== null && _a !== void 0 ? _a : (this._promise = new Promise((resolve) => (this._resolve = resolve))); + } + /** + * Resolves the promise which may be awaited + */ + resume() { + var _a; + (_a = this._resolve) === null || _a === void 0 ? void 0 : _a.call(this); + this._promise = this._resolve = undefined; + } +} + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +class AsyncReplaceDirective extends AsyncDirective { + constructor() { + super(...arguments); + this.__weakThis = new PseudoWeakRef(this); + this.__pauser = new Pauser(); + } + // @ts-expect-error value not used, but we want a nice parameter for docs + // eslint-disable-next-line @typescript-eslint/no-unused-vars + render(value, _mapper) { + return noChange; + } + update(_part, [value, mapper]) { + // If our initial render occurs while disconnected, ensure that the pauser + // and weakThis are in the disconnected state + if (!this.isConnected) { + this.disconnected(); + } + // If we've already set up this particular iterable, we don't need + // to do anything. + if (value === this.__value) { + return; + } + this.__value = value; + let i = 0; + const { __weakThis: weakThis, __pauser: pauser } = this; + // Note, the callback avoids closing over `this` so that the directive + // can be gc'ed before the promise resolves; instead `this` is retrieved + // from `weakThis`, which can break the hard reference in the closure when + // the directive disconnects + forAwaitOf(value, async (v) => { + // The while loop here handles the case that the connection state + // thrashes, causing the pauser to resume and then get re-paused + while (pauser.get()) { + await pauser.get(); + } + // If the callback gets here and there is no `this`, it means that the + // directive has been disconnected and garbage collected and we don't + // need to do anything else + const _this = weakThis.deref(); + if (_this !== undefined) { + // Check to make sure that value is the still the current value of + // the part, and if not bail because a new value owns this part + if (_this.__value !== value) { + return false; + } + // As a convenience, because functional-programming-style + // transforms of iterables and async iterables requires a library, + // we accept a mapper function. This is especially convenient for + // rendering a template for each item. + if (mapper !== undefined) { + v = mapper(v, i); + } + _this.commitValue(v, i); + i++; + } + return true; + }); + return noChange; + } + // Override point for AsyncAppend to append rather than replace + commitValue(value, _index) { + this.setValue(value); + } + disconnected() { + this.__weakThis.disconnect(); + this.__pauser.pause(); + } + reconnected() { + this.__weakThis.reconnect(this); + this.__pauser.resume(); + } +} +/** + * A directive that renders the items of an async iterable[1], replacing + * previous values with new values, so that only one value is ever rendered + * at a time. This directive may be used in any expression type. + * + * Async iterables are objects with a `[Symbol.asyncIterator]` method, which + * returns an iterator who's `next()` method returns a Promise. When a new + * value is available, the Promise resolves and the value is rendered to the + * Part controlled by the directive. If another value other than this + * directive has been set on the Part, the iterable will no longer be listened + * to and new values won't be written to the Part. + * + * [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of + * + * @param value An async iterable + * @param mapper An optional function that maps from (value, index) to another + * value. Useful for generating templates for each item in the iterable. + */ +const asyncReplace = directive(AsyncReplaceDirective); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +class AsyncAppendDirective extends AsyncReplaceDirective { + // Override AsyncReplace to narrow the allowed part type to ChildPart only + constructor(partInfo) { + super(partInfo); + if (partInfo.type !== PartType.CHILD) { + throw new Error('asyncAppend can only be used in child expressions'); + } + } + // Override AsyncReplace to save the part since we need to append into it + update(part, params) { + this.__childPart = part; + return super.update(part, params); + } + // Override AsyncReplace to append rather than replace + commitValue(value, index) { + // When we get the first value, clear the part. This lets the + // previous value display until we can replace it. + if (index === 0) { + clearPart(this.__childPart); + } + // Create and insert a new part and set its value to the next value + const newPart = insertPart(this.__childPart); + setChildPartValue(newPart, value); + } +} +/** + * A directive that renders the items of an async iterable[1], appending new + * values after previous values, similar to the built-in support for iterables. + * This directive is usable only in child expressions. + * + * Async iterables are objects with a [Symbol.asyncIterator] method, which + * returns an iterator who's `next()` method returns a Promise. When a new + * value is available, the Promise resolves and the value is appended to the + * Part controlled by the directive. If another value other than this + * directive has been set on the Part, the iterable will no longer be listened + * to and new values won't be written to the Part. + * + * [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of + * + * @param value An async iterable + * @param mapper An optional function that maps from (value, index) to another + * value. Useful for generating templates for each item in the iterable. + */ +const asyncAppend = directive(AsyncAppendDirective); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +class CacheDirective extends Directive { + constructor(partInfo) { + super(partInfo); + this._templateCache = new WeakMap(); + } + render(v) { + // Return an array of the value to induce lit-html to create a ChildPart + // for the value that we can move into the cache. + return [v]; + } + update(containerPart, [v]) { + // If the previous value is a TemplateResult and the new value is not, + // or is a different Template as the previous value, move the child part + // into the cache. + if (isTemplateResult(this._value) && + (!isTemplateResult(v) || this._value.strings !== v.strings)) { + // This is always an array because we return [v] in render() + const partValue = getCommittedValue(containerPart); + const childPart = partValue.pop(); + let cachedContainerPart = this._templateCache.get(this._value.strings); + if (cachedContainerPart === undefined) { + const fragment = document.createDocumentFragment(); + cachedContainerPart = render(nothing, fragment); + cachedContainerPart.setConnected(false); + this._templateCache.set(this._value.strings, cachedContainerPart); + } + // Move into cache + setCommittedValue(cachedContainerPart, [childPart]); + insertPart(cachedContainerPart, undefined, childPart); + } + // If the new value is a TemplateResult and the previous value is not, + // or is a different Template as the previous value, restore the child + // part from the cache. + if (isTemplateResult(v)) { + if (!isTemplateResult(this._value) || this._value.strings !== v.strings) { + const cachedContainerPart = this._templateCache.get(v.strings); + if (cachedContainerPart !== undefined) { + // Move the cached part back into the container part value + const partValue = getCommittedValue(cachedContainerPart); + const cachedPart = partValue.pop(); + // Move cached part back into DOM + clearPart(containerPart); + insertPart(containerPart, undefined, cachedPart); + setCommittedValue(containerPart, [cachedPart]); + } + } + this._value = v; + } + else { + this._value = undefined; + } + return this.render(v); + } +} +/** + * Enables fast switching between multiple templates by caching the DOM nodes + * and TemplateInstances produced by the templates. + * + * Example: + * + * ```js + * let checked = false; + * + * html` + * ${cache(checked ? html`input is checked` : html`input is not checked`)} + * ` + * ``` + */ +const cache = directive(CacheDirective); + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +/** + * Chooses and evaluates a template function from a list based on matching + * the given `value` to a case. + * + * Cases are structured as `[caseValue, func]`. `value` is matched to + * `caseValue` by strict equality. The first match is selected. Case values + * can be of any type including primitives, objects, and symbols. + * + * This is similar to a switch statement, but as an expression and without + * fallthrough. + * + * @example + * + * ```ts + * render() { + * return html` + * ${choose(this.section, [ + * ['home', () => html`<h1>Home</h1>`], + * ['about', () => html`<h1>About</h1>`] + * ], + * () => html`<h1>Error</h1>`)} + * `; + * } + * ``` + */ +const choose = (value, cases, defaultCase) => { + for (const c of cases) { + const caseValue = c[0]; + if (caseValue === value) { + const fn = c[1]; + return fn(); + } + } + return defaultCase === null || defaultCase === void 0 ? void 0 : defaultCase(); +}; + +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +class ClassMapDirective extends Directive { + constructor(partInfo) { + var _a; + super(partInfo); + if (partInfo.type !== PartType.ATTRIBUTE || + partInfo.name !== 'class' || + ((_a = partInfo.strings) === null || _a === void 0 ? void 0 : _a.length) > 2) { + throw new Error('`classMap()` can only be used in the `class` attribute ' + + 'and must be the only part in the attribute.'); + } + } + render(classInfo) { + // Add spaces to ensure separation from static classes + return (' ' + + Object.keys(classInfo) + .filter((key) => classInfo[key]) + .join(' ') + + ' '); + } + update(part, [classInfo]) { + var _a, _b; + // Remember dynamic classes on the first render + if (this._previousClasses === undefined) { + this._previousClasses = new Set(); + if (part.strings !== undefined) { + this._staticClasses = new Set(part.strings + .join(' ') + .split(/\s/) + .filter((s) => s !== '')); + } + for (const name in classInfo) { + if (classInfo[name] && !((_a = this._staticClasses) === null || _a === void 0 ? void 0 : _a.has(name))) { + this._previousClasses.add(name); + } + } + return this.render(classInfo); + } + const classList = part.element.classList; + // Remove old classes that no longer apply + // We use forEach() instead of for-of so that we don't require down-level + // iteration. + this._previousClasses.forEach((name) => { + if (!(name in classInfo)) { + classList.remove(name); + this._previousClasses.delete(name); + } + }); + // Add or remove classes based on their classMap value + for (const name in classInfo) { + // We explicitly want a loose truthy check of `value` because it seems + // more convenient that '' and 0 are skipped. + const value = !!classInfo[name]; + if (value !== this._previousClasses.has(name) && + !((_b = this._staticClasses) === null || _b === void 0 ? void 0 : _b.has(name))) { + if (value) { + classList.add(name); + this._previousClasses.add(name); + } + else { + classList.remove(name); + this._previousClasses.delete(name); + } + } + } + return noChange; + } +} +/** + * A directive that applies dynamic CSS classes. + * + * This must be used in the `class` attribute and must be the only part used in + * the attribute. It takes each property in the `classInfo` argument and adds + * the property name to the element's `classList` if the property value is + * truthy; if the property value is falsey, the property name is removed from + * the element's `class`. + * + * For example `{foo: bar}` applies the class `foo` if the value of `bar` is + * truthy. + * + * @param classInfo + */ +const classMap = directive(ClassMapDirective); + +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +// A sentinal that indicates guard() hasn't rendered anything yet +const initialValue = {}; +class GuardDirective extends Directive { + constructor() { + super(...arguments); + this._previousValue = initialValue; + } + render(_value, f) { + return f(); + } + update(_part, [value, f]) { + if (Array.isArray(value)) { + // Dirty-check arrays by item + if (Array.isArray(this._previousValue) && + this._previousValue.length === value.length && + value.every((v, i) => v === this._previousValue[i])) { + return noChange; + } + } + else if (this._previousValue === value) { + // Dirty-check non-arrays by identity + return noChange; + } + // Copy the value if it's an array so that if it's mutated we don't forget + // what the previous values were. + this._previousValue = Array.isArray(value) ? Array.from(value) : value; + const r = this.render(value, f); + return r; + } +} +/** + * Prevents re-render of a template function until a single value or an array of + * values changes. + * + * Values are checked against previous values with strict equality (`===`), and + * so the check won't detect nested property changes inside objects or arrays. + * Arrays values have each item checked against the previous value at the same + * index with strict equality. Nested arrays are also checked only by strict + * equality. + * + * Example: + * + * ```js + * html` + * <div> + * ${guard([user.id, company.id], () => html`...`)} + * </div> + * ` + * ``` + * + * In this case, the template only rerenders if either `user.id` or `company.id` + * changes. + * + * guard() is useful with immutable data patterns, by preventing expensive work + * until data updates. + * + * Example: + * + * ```js + * html` + * <div> + * ${guard([immutableItems], () => immutableItems.map(i => html`${i}`))} + * </div> + * ` + * ``` + * + * In this case, items are mapped over only when the array reference changes. + * + * @param value the value to check before re-rendering + * @param f the template function + */ +const guard = directive(GuardDirective); + +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +/** + * For AttributeParts, sets the attribute if the value is defined and removes + * the attribute if the value is undefined. + * + * For other part types, this directive is a no-op. + */ +const ifDefined = (value) => value !== null && value !== void 0 ? value : nothing; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +function* join(items, joiner) { + const isFunction = typeof joiner === 'function'; + if (items !== undefined) { + let i = -1; + for (const value of items) { + if (i > -1) { + yield isFunction ? joiner(i) : joiner; + } + i++; + yield value; + } + } +} + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +class Keyed extends Directive { + constructor() { + super(...arguments); + this.key = nothing; + } + render(k, v) { + this.key = k; + return v; + } + update(part, [k, v]) { + if (k !== this.key) { + // Clear the part before returning a value. The one-arg form of + // setCommittedValue sets the value to a sentinel which forces a + // commit the next render. + setCommittedValue(part); + this.key = k; + } + return v; + } +} +/** + * Associates a renderable value with a unique key. When the key changes, the + * previous DOM is removed and disposed before rendering the next value, even + * if the value - such as a template - is the same. + * + * This is useful for forcing re-renders of stateful components, or working + * with code that expects new data to generate new HTML elements, such as some + * animation techniques. + */ +const keyed = directive(Keyed); + +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +class LiveDirective extends Directive { + constructor(partInfo) { + super(partInfo); + if (!(partInfo.type === PartType.PROPERTY || + partInfo.type === PartType.ATTRIBUTE || + partInfo.type === PartType.BOOLEAN_ATTRIBUTE)) { + throw new Error('The `live` directive is not allowed on child or event bindings'); + } + if (!isSingleExpression(partInfo)) { + throw new Error('`live` bindings can only contain a single expression'); + } + } + render(value) { + return value; + } + update(part, [value]) { + if (value === noChange || value === nothing) { + return value; + } + const element = part.element; + const name = part.name; + if (part.type === PartType.PROPERTY) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (value === element[name]) { + return noChange; + } + } + else if (part.type === PartType.BOOLEAN_ATTRIBUTE) { + if (!!value === element.hasAttribute(name)) { + return noChange; + } + } + else if (part.type === PartType.ATTRIBUTE) { + if (element.getAttribute(name) === String(value)) { + return noChange; + } + } + // Resets the part's value, causing its dirty-check to fail so that it + // always sets the value. + setCommittedValue(part); + return value; + } +} +/** + * Checks binding values against live DOM values, instead of previously bound + * values, when determining whether to update the value. + * + * This is useful for cases where the DOM value may change from outside of + * lit-html, such as with a binding to an `<input>` element's `value` property, + * a content editable elements text, or to a custom element that changes it's + * own properties or attributes. + * + * In these cases if the DOM value changes, but the value set through lit-html + * bindings hasn't, lit-html won't know to update the DOM value and will leave + * it alone. If this is not what you want--if you want to overwrite the DOM + * value with the bound value no matter what--use the `live()` directive: + * + * ```js + * html`<input .value=${live(x)}>` + * ``` + * + * `live()` performs a strict equality check against the live DOM value, and if + * the new value is equal to the live value, does nothing. This means that + * `live()` should not be used when the binding will cause a type conversion. If + * you use `live()` with an attribute binding, make sure that only strings are + * passed in, or the binding will update every render. + */ +const live = directive(LiveDirective); + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +/** + * Returns an iterable containing the result of calling `f(value)` on each + * value in `items`. + * + * @example + * + * ```ts + * render() { + * return html` + * <ul> + * ${map(items, (i) => html`<li>${i}</li>`)} + * </ul> + * `; + * } + * ``` + */ +function* map(items, f) { + if (items !== undefined) { + let i = 0; + for (const value of items) { + yield f(value, i++); + } + } +} + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +function* range(startOrEnd, end, step = 1) { + const start = end === undefined ? 0 : startOrEnd; + end !== null && end !== void 0 ? end : (end = startOrEnd); + for (let i = start; step > 0 ? i < end : end < i; i += step) { + yield i; + } +} + +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +/** + * Creates a new Ref object, which is container for a reference to an element. + */ +const createRef = () => new Ref(); +/** + * An object that holds a ref value. + */ +class Ref { +} +// When callbacks are used for refs, this map tracks the last value the callback +// was called with, for ensuring a directive doesn't clear the ref if the ref +// has already been rendered to a new spot. It is double-keyed on both the +// context (`options.host`) and the callback, since we auto-bind class methods +// to `options.host`. +const lastElementForContextAndCallback = new WeakMap(); +class RefDirective extends AsyncDirective { + render(_ref) { + return nothing; + } + update(part, [ref]) { + var _a; + const refChanged = ref !== this._ref; + if (refChanged && this._ref !== undefined) { + // The ref passed to the directive has changed; + // unset the previous ref's value + this._updateRefValue(undefined); + } + if (refChanged || this._lastElementForRef !== this._element) { + // We either got a new ref or this is the first render; + // store the ref/element & update the ref value + this._ref = ref; + this._context = (_a = part.options) === null || _a === void 0 ? void 0 : _a.host; + this._updateRefValue((this._element = part.element)); + } + return nothing; + } + _updateRefValue(element) { + var _a; + if (typeof this._ref === 'function') { + // If the current ref was called with a previous value, call with + // `undefined`; We do this to ensure callbacks are called in a consistent + // way regardless of whether a ref might be moving up in the tree (in + // which case it would otherwise be called with the new value before the + // previous one unsets it) and down in the tree (where it would be unset + // before being set). Note that element lookup is keyed by + // both the context and the callback, since we allow passing unbound + // functions that are called on options.host, and we want to treat + // these as unique "instances" of a function. + const context = (_a = this._context) !== null && _a !== void 0 ? _a : globalThis; + let lastElementForCallback = lastElementForContextAndCallback.get(context); + if (lastElementForCallback === undefined) { + lastElementForCallback = new WeakMap(); + lastElementForContextAndCallback.set(context, lastElementForCallback); + } + if (lastElementForCallback.get(this._ref) !== undefined) { + this._ref.call(this._context, undefined); + } + lastElementForCallback.set(this._ref, element); + // Call the ref with the new element value + if (element !== undefined) { + this._ref.call(this._context, element); + } + } + else { + this._ref.value = element; + } + } + get _lastElementForRef() { + var _a, _b, _c; + return typeof this._ref === 'function' + ? (_b = lastElementForContextAndCallback + .get((_a = this._context) !== null && _a !== void 0 ? _a : globalThis)) === null || _b === void 0 ? void 0 : _b.get(this._ref) + : (_c = this._ref) === null || _c === void 0 ? void 0 : _c.value; + } + disconnected() { + // Only clear the box if our element is still the one in it (i.e. another + // directive instance hasn't rendered its element to it before us); that + // only happens in the event of the directive being cleared (not via manual + // disconnection) + if (this._lastElementForRef === this._element) { + this._updateRefValue(undefined); + } + } + reconnected() { + // If we were manually disconnected, we can safely put our element back in + // the box, since no rendering could have occurred to change its state + this._updateRefValue(this._element); + } +} +/** + * Sets the value of a Ref object or calls a ref callback with the element it's + * bound to. + * + * A Ref object acts as a container for a reference to an element. A ref + * callback is a function that takes an element as its only argument. + * + * The ref directive sets the value of the Ref object or calls the ref callback + * during rendering, if the referenced element changed. + * + * Note: If a ref callback is rendered to a different element position or is + * removed in a subsequent render, it will first be called with `undefined`, + * followed by another call with the new element it was rendered to (if any). + * + * ```js + * // Using Ref object + * const inputRef = createRef(); + * render(html`<input ${ref(inputRef)}>`, container); + * inputRef.value.focus(); + * + * // Using callback + * const callback = (inputElement) => inputElement.focus(); + * render(html`<input ${ref(callback)}>`, container); + * ``` + */ +const ref = directive(RefDirective); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +// Helper for generating a map of array item to its index over a subset +// of an array (used to lazily generate `newKeyToIndexMap` and +// `oldKeyToIndexMap`) +const generateMap = (list, start, end) => { + const map = new Map(); + for (let i = start; i <= end; i++) { + map.set(list[i], i); + } + return map; +}; +class RepeatDirective extends Directive { + constructor(partInfo) { + super(partInfo); + if (partInfo.type !== PartType.CHILD) { + throw new Error('repeat() can only be used in text expressions'); + } + } + _getValuesAndKeys(items, keyFnOrTemplate, template) { + let keyFn; + if (template === undefined) { + template = keyFnOrTemplate; + } + else if (keyFnOrTemplate !== undefined) { + keyFn = keyFnOrTemplate; + } + const keys = []; + const values = []; + let index = 0; + for (const item of items) { + keys[index] = keyFn ? keyFn(item, index) : index; + values[index] = template(item, index); + index++; + } + return { + values, + keys, + }; + } + render(items, keyFnOrTemplate, template) { + return this._getValuesAndKeys(items, keyFnOrTemplate, template).values; + } + update(containerPart, [items, keyFnOrTemplate, template]) { + var _a; + // Old part & key lists are retrieved from the last update (which may + // be primed by hydration) + const oldParts = getCommittedValue(containerPart); + const { values: newValues, keys: newKeys } = this._getValuesAndKeys(items, keyFnOrTemplate, template); + // We check that oldParts, the committed value, is an Array as an + // indicator that the previous value came from a repeat() call. If + // oldParts is not an Array then this is the first render and we return + // an array for lit-html's array handling to render, and remember the + // keys. + if (!Array.isArray(oldParts)) { + this._itemKeys = newKeys; + return newValues; + } + // In SSR hydration it's possible for oldParts to be an arrray but for us + // to not have item keys because the update() hasn't run yet. We set the + // keys to an empty array. This will cause all oldKey/newKey comparisons + // to fail and execution to fall to the last nested brach below which + // reuses the oldPart. + const oldKeys = ((_a = this._itemKeys) !== null && _a !== void 0 ? _a : (this._itemKeys = [])); + // New part list will be built up as we go (either reused from + // old parts or created for new keys in this update). This is + // saved in the above cache at the end of the update. + const newParts = []; + // Maps from key to index for current and previous update; these + // are generated lazily only when needed as a performance + // optimization, since they are only required for multiple + // non-contiguous changes in the list, which are less common. + let newKeyToIndexMap; + let oldKeyToIndexMap; + // Head and tail pointers to old parts and new values + let oldHead = 0; + let oldTail = oldParts.length - 1; + let newHead = 0; + let newTail = newValues.length - 1; + // Overview of O(n) reconciliation algorithm (general approach + // based on ideas found in ivi, vue, snabbdom, etc.): + // + // * We start with the list of old parts and new values (and + // arrays of their respective keys), head/tail pointers into + // each, and we build up the new list of parts by updating + // (and when needed, moving) old parts or creating new ones. + // The initial scenario might look like this (for brevity of + // the diagrams, the numbers in the array reflect keys + // associated with the old parts or new values, although keys + // and parts/values are actually stored in parallel arrays + // indexed using the same head/tail pointers): + // + // oldHead v v oldTail + // oldKeys: [0, 1, 2, 3, 4, 5, 6] + // newParts: [ , , , , , , ] + // newKeys: [0, 2, 1, 4, 3, 7, 6] <- reflects the user's new + // item order + // newHead ^ ^ newTail + // + // * Iterate old & new lists from both sides, updating, + // swapping, or removing parts at the head/tail locations + // until neither head nor tail can move. + // + // * Example below: keys at head pointers match, so update old + // part 0 in-place (no need to move it) and record part 0 in + // the `newParts` list. The last thing we do is advance the + // `oldHead` and `newHead` pointers (will be reflected in the + // next diagram). + // + // oldHead v v oldTail + // oldKeys: [0, 1, 2, 3, 4, 5, 6] + // newParts: [0, , , , , , ] <- heads matched: update 0 + // newKeys: [0, 2, 1, 4, 3, 7, 6] and advance both oldHead + // & newHead + // newHead ^ ^ newTail + // + // * Example below: head pointers don't match, but tail + // pointers do, so update part 6 in place (no need to move + // it), and record part 6 in the `newParts` list. Last, + // advance the `oldTail` and `oldHead` pointers. + // + // oldHead v v oldTail + // oldKeys: [0, 1, 2, 3, 4, 5, 6] + // newParts: [0, , , , , , 6] <- tails matched: update 6 + // newKeys: [0, 2, 1, 4, 3, 7, 6] and advance both oldTail + // & newTail + // newHead ^ ^ newTail + // + // * If neither head nor tail match; next check if one of the + // old head/tail items was removed. We first need to generate + // the reverse map of new keys to index (`newKeyToIndexMap`), + // which is done once lazily as a performance optimization, + // since we only hit this case if multiple non-contiguous + // changes were made. Note that for contiguous removal + // anywhere in the list, the head and tails would advance + // from either end and pass each other before we get to this + // case and removals would be handled in the final while loop + // without needing to generate the map. + // + // * Example below: The key at `oldTail` was removed (no longer + // in the `newKeyToIndexMap`), so remove that part from the + // DOM and advance just the `oldTail` pointer. + // + // oldHead v v oldTail + // oldKeys: [0, 1, 2, 3, 4, 5, 6] + // newParts: [0, , , , , , 6] <- 5 not in new map: remove + // newKeys: [0, 2, 1, 4, 3, 7, 6] 5 and advance oldTail + // newHead ^ ^ newTail + // + // * Once head and tail cannot move, any mismatches are due to + // either new or moved items; if a new key is in the previous + // "old key to old index" map, move the old part to the new + // location, otherwise create and insert a new part. Note + // that when moving an old part we null its position in the + // oldParts array if it lies between the head and tail so we + // know to skip it when the pointers get there. + // + // * Example below: neither head nor tail match, and neither + // were removed; so find the `newHead` key in the + // `oldKeyToIndexMap`, and move that old part's DOM into the + // next head position (before `oldParts[oldHead]`). Last, + // null the part in the `oldPart` array since it was + // somewhere in the remaining oldParts still to be scanned + // (between the head and tail pointers) so that we know to + // skip that old part on future iterations. + // + // oldHead v v oldTail + // oldKeys: [0, 1, -, 3, 4, 5, 6] + // newParts: [0, 2, , , , , 6] <- stuck: update & move 2 + // newKeys: [0, 2, 1, 4, 3, 7, 6] into place and advance + // newHead + // newHead ^ ^ newTail + // + // * Note that for moves/insertions like the one above, a part + // inserted at the head pointer is inserted before the + // current `oldParts[oldHead]`, and a part inserted at the + // tail pointer is inserted before `newParts[newTail+1]`. The + // seeming asymmetry lies in the fact that new parts are + // moved into place outside in, so to the right of the head + // pointer are old parts, and to the right of the tail + // pointer are new parts. + // + // * We always restart back from the top of the algorithm, + // allowing matching and simple updates in place to + // continue... + // + // * Example below: the head pointers once again match, so + // simply update part 1 and record it in the `newParts` + // array. Last, advance both head pointers. + // + // oldHead v v oldTail + // oldKeys: [0, 1, -, 3, 4, 5, 6] + // newParts: [0, 2, 1, , , , 6] <- heads matched: update 1 + // newKeys: [0, 2, 1, 4, 3, 7, 6] and advance both oldHead + // & newHead + // newHead ^ ^ newTail + // + // * As mentioned above, items that were moved as a result of + // being stuck (the final else clause in the code below) are + // marked with null, so we always advance old pointers over + // these so we're comparing the next actual old value on + // either end. + // + // * Example below: `oldHead` is null (already placed in + // newParts), so advance `oldHead`. + // + // oldHead v v oldTail + // oldKeys: [0, 1, -, 3, 4, 5, 6] <- old head already used: + // newParts: [0, 2, 1, , , , 6] advance oldHead + // newKeys: [0, 2, 1, 4, 3, 7, 6] + // newHead ^ ^ newTail + // + // * Note it's not critical to mark old parts as null when they + // are moved from head to tail or tail to head, since they + // will be outside the pointer range and never visited again. + // + // * Example below: Here the old tail key matches the new head + // key, so the part at the `oldTail` position and move its + // DOM to the new head position (before `oldParts[oldHead]`). + // Last, advance `oldTail` and `newHead` pointers. + // + // oldHead v v oldTail + // oldKeys: [0, 1, -, 3, 4, 5, 6] + // newParts: [0, 2, 1, 4, , , 6] <- old tail matches new + // newKeys: [0, 2, 1, 4, 3, 7, 6] head: update & move 4, + // advance oldTail & newHead + // newHead ^ ^ newTail + // + // * Example below: Old and new head keys match, so update the + // old head part in place, and advance the `oldHead` and + // `newHead` pointers. + // + // oldHead v oldTail + // oldKeys: [0, 1, -, 3, 4, 5, 6] + // newParts: [0, 2, 1, 4, 3, ,6] <- heads match: update 3 + // newKeys: [0, 2, 1, 4, 3, 7, 6] and advance oldHead & + // newHead + // newHead ^ ^ newTail + // + // * Once the new or old pointers move past each other then all + // we have left is additions (if old list exhausted) or + // removals (if new list exhausted). Those are handled in the + // final while loops at the end. + // + // * Example below: `oldHead` exceeded `oldTail`, so we're done + // with the main loop. Create the remaining part and insert + // it at the new head position, and the update is complete. + // + // (oldHead > oldTail) + // oldKeys: [0, 1, -, 3, 4, 5, 6] + // newParts: [0, 2, 1, 4, 3, 7 ,6] <- create and insert 7 + // newKeys: [0, 2, 1, 4, 3, 7, 6] + // newHead ^ newTail + // + // * Note that the order of the if/else clauses is not + // important to the algorithm, as long as the null checks + // come first (to ensure we're always working on valid old + // parts) and that the final else clause comes last (since + // that's where the expensive moves occur). The order of + // remaining clauses is is just a simple guess at which cases + // will be most common. + // + // * Note, we could calculate the longest + // increasing subsequence (LIS) of old items in new position, + // and only move those not in the LIS set. However that costs + // O(nlogn) time and adds a bit more code, and only helps + // make rare types of mutations require fewer moves. The + // above handles removes, adds, reversal, swaps, and single + // moves of contiguous items in linear time, in the minimum + // number of moves. As the number of multiple moves where LIS + // might help approaches a random shuffle, the LIS + // optimization becomes less helpful, so it seems not worth + // the code at this point. Could reconsider if a compelling + // case arises. + while (oldHead <= oldTail && newHead <= newTail) { + if (oldParts[oldHead] === null) { + // `null` means old part at head has already been used + // below; skip + oldHead++; + } + else if (oldParts[oldTail] === null) { + // `null` means old part at tail has already been used + // below; skip + oldTail--; + } + else if (oldKeys[oldHead] === newKeys[newHead]) { + // Old head matches new head; update in place + newParts[newHead] = setChildPartValue(oldParts[oldHead], newValues[newHead]); + oldHead++; + newHead++; + } + else if (oldKeys[oldTail] === newKeys[newTail]) { + // Old tail matches new tail; update in place + newParts[newTail] = setChildPartValue(oldParts[oldTail], newValues[newTail]); + oldTail--; + newTail--; + } + else if (oldKeys[oldHead] === newKeys[newTail]) { + // Old head matches new tail; update and move to new tail + newParts[newTail] = setChildPartValue(oldParts[oldHead], newValues[newTail]); + insertPart(containerPart, newParts[newTail + 1], oldParts[oldHead]); + oldHead++; + newTail--; + } + else if (oldKeys[oldTail] === newKeys[newHead]) { + // Old tail matches new head; update and move to new head + newParts[newHead] = setChildPartValue(oldParts[oldTail], newValues[newHead]); + insertPart(containerPart, oldParts[oldHead], oldParts[oldTail]); + oldTail--; + newHead++; + } + else { + if (newKeyToIndexMap === undefined) { + // Lazily generate key-to-index maps, used for removals & + // moves below + newKeyToIndexMap = generateMap(newKeys, newHead, newTail); + oldKeyToIndexMap = generateMap(oldKeys, oldHead, oldTail); + } + if (!newKeyToIndexMap.has(oldKeys[oldHead])) { + // Old head is no longer in new list; remove + removePart(oldParts[oldHead]); + oldHead++; + } + else if (!newKeyToIndexMap.has(oldKeys[oldTail])) { + // Old tail is no longer in new list; remove + removePart(oldParts[oldTail]); + oldTail--; + } + else { + // Any mismatches at this point are due to additions or + // moves; see if we have an old part we can reuse and move + // into place + const oldIndex = oldKeyToIndexMap.get(newKeys[newHead]); + const oldPart = oldIndex !== undefined ? oldParts[oldIndex] : null; + if (oldPart === null) { + // No old part for this value; create a new one and + // insert it + const newPart = insertPart(containerPart, oldParts[oldHead]); + setChildPartValue(newPart, newValues[newHead]); + newParts[newHead] = newPart; + } + else { + // Reuse old part + newParts[newHead] = setChildPartValue(oldPart, newValues[newHead]); + insertPart(containerPart, oldParts[oldHead], oldPart); + // This marks the old part as having been used, so that + // it will be skipped in the first two checks above + oldParts[oldIndex] = null; + } + newHead++; + } + } + } + // Add parts for any remaining new values + while (newHead <= newTail) { + // For all remaining additions, we insert before last new + // tail, since old pointers are no longer valid + const newPart = insertPart(containerPart, newParts[newTail + 1]); + setChildPartValue(newPart, newValues[newHead]); + newParts[newHead++] = newPart; + } + // Remove any remaining unused old parts + while (oldHead <= oldTail) { + const oldPart = oldParts[oldHead++]; + if (oldPart !== null) { + removePart(oldPart); + } + } + // Save order of new parts for next round + this._itemKeys = newKeys; + // Directly set part value, bypassing it's dirty-checking + setCommittedValue(containerPart, newParts); + return noChange; + } +} +/** + * A directive that repeats a series of values (usually `TemplateResults`) + * generated from an iterable, and updates those items efficiently when the + * iterable changes based on user-provided `keys` associated with each item. + * + * Note that if a `keyFn` is provided, strict key-to-DOM mapping is maintained, + * meaning previous DOM for a given key is moved into the new position if + * needed, and DOM will never be reused with values for different keys (new DOM + * will always be created for new keys). This is generally the most efficient + * way to use `repeat` since it performs minimum unnecessary work for insertions + * and removals. + * + * The `keyFn` takes two parameters, the item and its index, and returns a unique key value. + * + * ```js + * html` + * <ol> + * ${repeat(this.items, (item) => item.id, (item, index) => { + * return html`<li>${index}: ${item.name}</li>`; + * })} + * </ol> + * ` + * ``` + * + * **Important**: If providing a `keyFn`, keys *must* be unique for all items in a + * given call to `repeat`. The behavior when two or more items have the same key + * is undefined. + * + * If no `keyFn` is provided, this directive will perform similar to mapping + * items to values, and DOM will be reused against potentially different items. + */ +const repeat = directive(RepeatDirective); + +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +class StyleMapDirective extends Directive { + constructor(partInfo) { + var _a; + super(partInfo); + if (partInfo.type !== PartType.ATTRIBUTE || + partInfo.name !== 'style' || + ((_a = partInfo.strings) === null || _a === void 0 ? void 0 : _a.length) > 2) { + throw new Error('The `styleMap` directive must be used in the `style` attribute ' + + 'and must be the only part in the attribute.'); + } + } + render(styleInfo) { + return Object.keys(styleInfo).reduce((style, prop) => { + return style + prop.slice(0, 0); + }, ''); + } + update(part, [styleInfo]) { + const { style } = part.element; + if (this._previousStyleProperties === undefined) { + this._previousStyleProperties = new Set(); + } + // Remove old properties that no longer exist in styleInfo + // We use forEach() instead of for-of so that re don't require down-level + // iteration. + this._previousStyleProperties.forEach((name) => { + // If the name isn't in styleInfo or it's null/undefined + if (styleInfo[name] == null) { + this._previousStyleProperties.delete(name); + if (name.includes('-')) { + style.removeProperty(name); + } + else { + // Note reset using empty string (vs null) as IE11 does not always + // reset via null (https://developer.mozilla.org/en-US/docs/Web/API/ElementCSSInlineStyle/style#setting_styles) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + style[name] = ''; + } + } + }); + // Add or update properties + for (const name in styleInfo) { + const value = styleInfo[name]; + if (value != null) { + this._previousStyleProperties.add(name); + if (name.includes('-')) { + style.setProperty(name, value); + } + else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + style[name] = value; + } + } + } + return noChange; + } +} +/** + * A directive that applies CSS properties to an element. + * + * `styleMap` can only be used in the `style` attribute and must be the only + * expression in the attribute. It takes the property names in the + * {@link StyleInfo styleInfo} object and adds the property values as CSS + * properties. Property names with dashes (`-`) are assumed to be valid CSS + * property names and set on the element's style object using `setProperty()`. + * Names without dashes are assumed to be camelCased JavaScript property names + * and set on the element's style object using property assignment, allowing the + * style object to translate JavaScript-style names to CSS property names. + * + * For example `styleMap({backgroundColor: 'red', 'border-top': '5px', '--size': + * '0'})` sets the `background-color`, `border-top` and `--size` properties. + * + * @param styleInfo + * @see {@link https://lit.dev/docs/templates/directives/#stylemap styleMap code samples on Lit.dev} + */ +const styleMap = directive(StyleMapDirective); + +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +class TemplateContentDirective extends Directive { + constructor(partInfo) { + super(partInfo); + if (partInfo.type !== PartType.CHILD) { + throw new Error('templateContent can only be used in child bindings'); + } + } + render(template) { + if (this._previousTemplate === template) { + return noChange; + } + this._previousTemplate = template; + return document.importNode(template.content, true); + } +} +/** + * Renders the content of a template element as HTML. + * + * Note, the template should be developer controlled and not user controlled. + * Rendering a user-controlled template with this directive + * could lead to cross-site-scripting vulnerabilities. + */ +const templateContent = directive(TemplateContentDirective); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const HTML_RESULT = 1; +class UnsafeHTMLDirective extends Directive { + constructor(partInfo) { + super(partInfo); + this._value = nothing; + if (partInfo.type !== PartType.CHILD) { + throw new Error(`${this.constructor.directiveName}() can only be used in child bindings`); + } + } + render(value) { + if (value === nothing || value == null) { + this._templateResult = undefined; + return (this._value = value); + } + if (value === noChange) { + return value; + } + if (typeof value != 'string') { + throw new Error(`${this.constructor.directiveName}() called with a non-string value`); + } + if (value === this._value) { + return this._templateResult; + } + this._value = value; + const strings = [value]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + strings.raw = strings; + // WARNING: impersonating a TemplateResult like this is extremely + // dangerous. Third-party directives should not do this. + return (this._templateResult = { + // Cast to a known set of integers that satisfy ResultType so that we + // don't have to export ResultType and possibly encourage this pattern. + // This property needs to remain unminified. + ['_$litType$']: this.constructor + .resultType, + strings, + values: [], + }); + } +} +UnsafeHTMLDirective.directiveName = 'unsafeHTML'; +UnsafeHTMLDirective.resultType = HTML_RESULT; +/** + * Renders the result as HTML, rather than text. + * + * The values `undefined`, `null`, and `nothing`, will all result in no content + * (empty string) being rendered. + * + * Note, this is unsafe to use with any user-provided input that hasn't been + * sanitized or escaped, as it may lead to cross-site-scripting + * vulnerabilities. + */ +const unsafeHTML = directive(UnsafeHTMLDirective); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const SVG_RESULT = 2; +class UnsafeSVGDirective extends UnsafeHTMLDirective { +} +UnsafeSVGDirective.directiveName = 'unsafeSVG'; +UnsafeSVGDirective.resultType = SVG_RESULT; +/** + * Renders the result as SVG, rather than text. + * + * The values `undefined`, `null`, and `nothing`, will all result in no content + * (empty string) being rendered. + * + * Note, this is unsafe to use with any user-provided input that hasn't been + * sanitized or escaped, as it may lead to cross-site-scripting + * vulnerabilities. + */ +const unsafeSVG = directive(UnsafeSVGDirective); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const isPromise = (x) => { + return !isPrimitive(x) && typeof x.then === 'function'; +}; +// Effectively infinity, but a SMI. +const _infinity = 0x3fffffff; +class UntilDirective extends AsyncDirective { + constructor() { + super(...arguments); + this.__lastRenderedIndex = _infinity; + this.__values = []; + this.__weakThis = new PseudoWeakRef(this); + this.__pauser = new Pauser(); + } + render(...args) { + var _a; + return (_a = args.find((x) => !isPromise(x))) !== null && _a !== void 0 ? _a : noChange; + } + update(_part, args) { + const previousValues = this.__values; + let previousLength = previousValues.length; + this.__values = args; + const weakThis = this.__weakThis; + const pauser = this.__pauser; + // If our initial render occurs while disconnected, ensure that the pauser + // and weakThis are in the disconnected state + if (!this.isConnected) { + this.disconnected(); + } + for (let i = 0; i < args.length; i++) { + // If we've rendered a higher-priority value already, stop. + if (i > this.__lastRenderedIndex) { + break; + } + const value = args[i]; + // Render non-Promise values immediately + if (!isPromise(value)) { + this.__lastRenderedIndex = i; + // Since a lower-priority value will never overwrite a higher-priority + // synchronous value, we can stop processing now. + return value; + } + // If this is a Promise we've already handled, skip it. + if (i < previousLength && value === previousValues[i]) { + continue; + } + // We have a Promise that we haven't seen before, so priorities may have + // changed. Forget what we rendered before. + this.__lastRenderedIndex = _infinity; + previousLength = 0; + // Note, the callback avoids closing over `this` so that the directive + // can be gc'ed before the promise resolves; instead `this` is retrieved + // from `weakThis`, which can break the hard reference in the closure when + // the directive disconnects + Promise.resolve(value).then(async (result) => { + // If we're disconnected, wait until we're (maybe) reconnected + // The while loop here handles the case that the connection state + // thrashes, causing the pauser to resume and then get re-paused + while (pauser.get()) { + await pauser.get(); + } + // If the callback gets here and there is no `this`, it means that the + // directive has been disconnected and garbage collected and we don't + // need to do anything else + const _this = weakThis.deref(); + if (_this !== undefined) { + const index = _this.__values.indexOf(value); + // If state.values doesn't contain the value, we've re-rendered without + // the value, so don't render it. Then, only render if the value is + // higher-priority than what's already been rendered. + if (index > -1 && index < _this.__lastRenderedIndex) { + _this.__lastRenderedIndex = index; + _this.setValue(result); + } + } + }); + } + return noChange; + } + disconnected() { + this.__weakThis.disconnect(); + this.__pauser.pause(); + } + reconnected() { + this.__weakThis.reconnect(this); + this.__pauser.resume(); + } +} +/** + * Renders one of a series of values, including Promises, to a Part. + * + * Values are rendered in priority order, with the first argument having the + * highest priority and the last argument having the lowest priority. If a + * value is a Promise, low-priority values will be rendered until it resolves. + * + * The priority of values can be used to create placeholder content for async + * data. For example, a Promise with pending content can be the first, + * highest-priority, argument, and a non_promise loading indicator template can + * be used as the second, lower-priority, argument. The loading indicator will + * render immediately, and the primary content will render when the Promise + * resolves. + * + * Example: + * + * ```js + * const content = fetch('./content.txt').then(r => r.text()); + * html`${until(content, html`<span>Loading...</span>`)}` + * ``` + */ +const until = directive(UntilDirective); +/** + * The type of the class that powers this directive. Necessary for naming the + * directive's return type. + */ +// export type {UntilDirective}; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +function when(condition, trueCase, falseCase) { + return condition ? trueCase() : falseCase === null || falseCase === void 0 ? void 0 : falseCase(); +} + +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +/** + * Prevents JSON injection attacks. + * + * The goals of this brand: + * 1) fast to check + * 2) code is small on the wire + * 3) multiple versions of Lit in a single page will all produce mutually + * interoperable StaticValues + * 4) normal JSON.parse (without an unusual reviver) can not produce a + * StaticValue + * + * Symbols satisfy (1), (2), and (4). We use Symbol.for to satisfy (3), but + * we don't care about the key, so we break ties via (2) and use the empty + * string. + */ +const brand = Symbol.for(''); +/** Safely extracts the string part of a StaticValue. */ +const unwrapStaticValue = (value) => { + if ((value === null || value === void 0 ? void 0 : value.r) !== brand) { + return undefined; + } + return value === null || value === void 0 ? void 0 : value['_$litStatic$']; +}; +/** + * Wraps a string so that it behaves like part of the static template + * strings instead of a dynamic value. + * + * Users must take care to ensure that adding the static string to the template + * results in well-formed HTML, or else templates may break unexpectedly. + * + * Note that this function is unsafe to use on untrusted content, as it will be + * directly parsed into HTML. Do not pass user input to this function + * without sanitizing it. + * + * Static values can be changed, but they will cause a complete re-render + * since they effectively create a new template. + */ +const unsafeStatic = (value) => ({ + ['_$litStatic$']: value, + r: brand, +}); +const textFromStatic = (value) => { + if (value['_$litStatic$'] !== undefined) { + return value['_$litStatic$']; + } + else { + throw new Error(`Value passed to 'literal' function must be a 'literal' result: ${value}. Use 'unsafeStatic' to pass non-literal values, but + take care to ensure page security.`); + } +}; +/** + * Tags a string literal so that it behaves like part of the static template + * strings instead of a dynamic value. + * + * The only values that may be used in template expressions are other tagged + * `literal` results or `unsafeStatic` values (note that untrusted content + * should never be passed to `unsafeStatic`). + * + * Users must take care to ensure that adding the static string to the template + * results in well-formed HTML, or else templates may break unexpectedly. + * + * Static values can be changed, but they will cause a complete re-render since + * they effectively create a new template. + */ +const literal = (strings, ...values) => ({ + ['_$litStatic$']: values.reduce((acc, v, idx) => acc + textFromStatic(v) + strings[idx + 1], strings[0]), + r: brand, +}); +const stringsCache = new Map(); +/** + * Wraps a lit-html template tag (`html` or `svg`) to add static value support. + */ +const withStatic = (coreTag) => (strings, ...values) => { + const l = values.length; + let staticValue; + let dynamicValue; + const staticStrings = []; + const dynamicValues = []; + let i = 0; + let hasStatics = false; + let s; + while (i < l) { + s = strings[i]; + // Collect any unsafeStatic values, and their following template strings + // so that we treat a run of template strings and unsafe static values as + // a single template string. + while (i < l && + ((dynamicValue = values[i]), + (staticValue = unwrapStaticValue(dynamicValue))) !== undefined) { + s += staticValue + strings[++i]; + hasStatics = true; + } + dynamicValues.push(dynamicValue); + staticStrings.push(s); + i++; + } + // If the last value isn't static (which would have consumed the last + // string), then we need to add the last string. + if (i === l) { + staticStrings.push(strings[l]); + } + if (hasStatics) { + const key = staticStrings.join('$$lit$$'); + strings = stringsCache.get(key); + if (strings === undefined) { + // Beware: in general this pattern is unsafe, and doing so may bypass + // lit's security checks and allow an attacker to execute arbitrary + // code and inject arbitrary content. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + staticStrings.raw = staticStrings; + stringsCache.set(key, (strings = staticStrings)); + } + values = dynamicValues; + } + return coreTag(strings, ...values); +}; +/** + * Interprets a template literal as an HTML template that can efficiently + * render to and update a container. + * + * Includes static value support from `lit-html/static.js`. + */ +const html = withStatic(html$1); +/** + * Interprets a template literal as an SVG template that can efficiently + * render to and update a container. + * + * Includes static value support from `lit-html/static.js`. + */ +const svg = withStatic(svg$1); + +export { AsyncDirective, AsyncReplaceDirective, CSSResult, Directive, LitElement, PartType, ReactiveElement, TemplateResultType, UnsafeHTMLDirective, UntilDirective, UpdatingElement, _$LE, _$LH, adoptStyles, asyncAppend, asyncReplace, cache, choose, classMap, clearPart, createRef, css, defaultConverter, directive, getCommittedValue, getCompatibleStyle, getDirectiveClass, guard, html$1 as html, ifDefined, insertPart, isDirectiveResult, isPrimitive, isServer, isSingleExpression, isTemplateResult, join, keyed, literal, live, map, noChange, notEqual, nothing, range, ref, removePart, render, repeat, setChildPartValue, setCommittedValue, html as staticHtml, svg as staticSvg, styleMap, supportsAdoptingStyleSheets, svg$1 as svg, templateContent, unsafeCSS, unsafeHTML, unsafeSVG, unsafeStatic, until, when, withStatic }; |