UNPKG

@google/model-viewer

Version:

Easily display interactive 3D models on the web and in AR!

1,058 lines (1,046 loc) 1.58 MB
/** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at * http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at * http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ /** * An expression marker with embedded unique key to avoid collision with * possible text in templates. */ `{{lit-${String(Math.random()).slice(2)}}}`; /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at * http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at * http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ /** * 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. */ window.trustedTypes && trustedTypes.createPolicy('lit-html', { createHTML: (s) => s }); /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at * http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at * http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ // Detect event listener options support. If the `capture` property is read // from the options object, then options are supported. If not, then the third // argument to add/removeEventListener is interpreted as the boolean capture // value so we should only pass the `capture` property. let eventOptionsSupported = false; // Wrap into an IIFE because MS Edge <= v41 does not support having try/catch // blocks right into the body of a module (() => { try { const options = { get capture() { eventOptionsSupported = true; return false; } }; // eslint-disable-next-line @typescript-eslint/no-explicit-any window.addEventListener('test', options, options); // eslint-disable-next-line @typescript-eslint/no-explicit-any window.removeEventListener('test', options, options); } catch (_e) { // event options not supported } })(); /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at * http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at * http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ // IMPORTANT: do not change the property name or the assignment expression. // This line will be used in regexes to search for lit-html usage. // TODO(justinfagnani): inject version number at build time if (typeof window !== 'undefined') { (window['litHtmlVersions'] || (window['litHtmlVersions'] = [])).push('1.3.0'); } /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at * http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at * http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ if (typeof window.ShadyCSS === 'undefined') ; else if (typeof window.ShadyCSS.prepareTemplateDom === 'undefined') { console.warn(`Incompatible ShadyCSS version detected. ` + `Please update to at least @webcomponents/webcomponentsjs@2.0.2 and ` + `@webcomponents/shadycss@1.3.1.`); } /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at * http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at * http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ var _a$c; /** * Use this module if you want to create your own base class extending * [[UpdatingElement]]. * @packageDocumentation */ /* * 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. */ window.JSCompiler_renameProperty = (prop, _obj) => prop; const defaultConverter = { toAttribute(value, type) { switch (type) { case Boolean: return value ? '' : null; case Object: case Array: // if the value is `null` or `undefined` pass this through // to allow removing/no change behavior. return value == null ? value : JSON.stringify(value); } return value; }, fromAttribute(value, type) { switch (type) { case Boolean: return value !== null; case Number: return value === null ? null : Number(value); case Object: case Array: return JSON.parse(value); } return value; } }; /** * 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 }; const STATE_HAS_UPDATED = 1; const STATE_UPDATE_REQUESTED = 1 << 2; const STATE_IS_REFLECTING_TO_ATTRIBUTE = 1 << 3; const STATE_IS_REFLECTING_TO_PROPERTY = 1 << 4; /** * 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 UpdatingElement extends HTMLElement { constructor() { super(); this.initialize(); } /** * Returns a list of attributes corresponding to the registered properties. * @nocollapse */ 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._classProperties.forEach((v, p) => { const attr = this._attributeNameForProperty(p, v); if (attr !== undefined) { this._attributeToPropertyMap.set(attr, p); attributes.push(attr); } }); return attributes; } /** * Ensures the private `_classProperties` property metadata is created. * In addition to `finalize` this is also called in `createProperty` to * ensure the `@property` decorator can add property metadata. */ /** @nocollapse */ static _ensureClassProperties() { // ensure private storage for property declarations. if (!this.hasOwnProperty(JSCompiler_renameProperty('_classProperties', this))) { this._classProperties = new Map(); // NOTE: Workaround IE11 not supporting Map constructor argument. const superProperties = Object.getPrototypeOf(this)._classProperties; if (superProperties !== undefined) { superProperties.forEach((v, k) => this._classProperties.set(k, v)); } } } /** * Creates a property accessor on the element prototype if one does not exist * and stores a 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: * * static createProperty(name, options) { * options = Object.assign(options, {myOption: true}); * super.createProperty(name, options); * } * * @nocollapse */ static createProperty(name, options = defaultPropertyDeclaration) { // Note, since this can be called by the `@property` decorator which // is called before `finalize`, we ensure storage exists for property // metadata. this._ensureClassProperties(); this._classProperties.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)) { return; } 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, * * 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 */ static getPropertyDescriptor(name, key, options) { return { // tslint:disable-next-line:no-any no symbol in index get() { return this[key]; }, set(value) { const oldValue = this[name]; this[key] = value; this .requestUpdateInternal(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 `createProperty`. * * @nocollapse * @final */ static getPropertyOptions(name) { return this._classProperties && this._classProperties.get(name) || defaultPropertyDeclaration; } /** * Creates property accessors for registered properties and ensures * any superclasses are also finalized. * @nocollapse */ static finalize() { // finalize any superclasses const superCtor = Object.getPrototypeOf(this); if (!superCtor.hasOwnProperty(finalized)) { superCtor.finalize(); } this[finalized] = true; this._ensureClassProperties(); // 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', this))) { const props = this.properties; // support symbols in properties (IE11 does not support this) const propKeys = [ ...Object.getOwnPropertyNames(props), ...(typeof Object.getOwnPropertySymbols === 'function') ? 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 TypeSript lack of support for symbol in // index types // tslint:disable-next-line:no-any no symbol in index this.createProperty(p, props[p]); } } } /** * 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)); } /** * Returns true if a property should request an update. * Called when a property value is set and uses the `hasChanged` * option for the property if present or a strict identity check. * @nocollapse */ static _valueHasChanged(value, old, hasChanged = notEqual) { return hasChanged(value, old); } /** * Returns the property value for the given attribute value. * Called via the `attributeChangedCallback` and uses the property's * `converter` or `converter.fromAttribute` property option. * @nocollapse */ static _propertyValueFromAttribute(value, options) { const type = options.type; const converter = options.converter || defaultConverter; const fromAttribute = (typeof converter === 'function' ? converter : converter.fromAttribute); return fromAttribute ? fromAttribute(value, type) : value; } /** * Returns the attribute value for the given property value. If this * returns undefined, the property will *not* be reflected to an attribute. * If this returns null, the attribute will be removed, otherwise the * attribute will be set to the value. * This uses the property's `reflect` and `type.toAttribute` property options. * @nocollapse */ static _propertyValueToAttribute(value, options) { if (options.reflect === undefined) { return; } const type = options.type; const converter = options.converter; const toAttribute = converter && converter.toAttribute || defaultConverter.toAttribute; return toAttribute(value, type); } /** * Performs element initialization. By default captures any pre-set values for * registered properties. */ initialize() { this._updateState = 0; this._updatePromise = new Promise((res) => this._enableUpdatingResolver = res); this._changedProperties = new Map(); this._saveInstanceProperties(); // ensures first update will be caught by an early access of // `updateComplete` this.requestUpdateInternal(); } /** * 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 ._classProperties.forEach((_v, p) => { if (this.hasOwnProperty(p)) { const value = this[p]; delete this[p]; if (!this._instanceProperties) { this._instanceProperties = new Map(); } this._instanceProperties.set(p, value); } }); } /** * Applies previously saved instance properties. */ _applyInstanceProperties() { // Use forEach so this works even if for/of loops are compiled to for loops // expecting arrays // tslint:disable-next-line:no-any this._instanceProperties.forEach((v, p) => this[p] = v); this._instanceProperties = undefined; } connectedCallback() { // Ensure first connection completes an update. Updates cannot complete // before connection. this.enableUpdating(); } enableUpdating() { if (this._enableUpdatingResolver !== undefined) { this._enableUpdatingResolver(); this._enableUpdatingResolver = undefined; } } /** * Allows for `super.disconnectedCallback()` in extensions while * reserving the possibility of making non-breaking feature additions * when disconnecting at some point in the future. */ disconnectedCallback() { } /** * Synchronizes property values when attributes change. */ attributeChangedCallback(name, old, value) { if (old !== value) { this._attributeToProperty(name, value); } } _propertyToAttribute(name, value, options = defaultPropertyDeclaration) { const ctor = this.constructor; const attr = ctor._attributeNameForProperty(name, options); if (attr !== undefined) { const attrValue = ctor._propertyValueToAttribute(value, options); // an undefined value does not change the attribute. if (attrValue === undefined) { return; } // 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._updateState = this._updateState | STATE_IS_REFLECTING_TO_ATTRIBUTE; if (attrValue == null) { this.removeAttribute(attr); } else { this.setAttribute(attr, attrValue); } // mark state not reflecting this._updateState = this._updateState & ~STATE_IS_REFLECTING_TO_ATTRIBUTE; } } _attributeToProperty(name, value) { // Use tracking info to avoid deserializing attribute value if it was // just set from a property setter. if (this._updateState & STATE_IS_REFLECTING_TO_ATTRIBUTE) { return; } const ctor = this.constructor; // Note, hint this as an `AttributeMap` so closure clearly understands // the type; it has issues with tracking types through statics // tslint:disable-next-line:no-unnecessary-type-assertion const propName = ctor._attributeToPropertyMap.get(name); if (propName !== undefined) { const options = ctor.getPropertyOptions(propName); // mark state reflecting this._updateState = this._updateState | STATE_IS_REFLECTING_TO_PROPERTY; this[propName] = // tslint:disable-next-line:no-any ctor._propertyValueFromAttribute(value, options); // mark state not reflecting this._updateState = this._updateState & ~STATE_IS_REFLECTING_TO_PROPERTY; } } /** * This protected version of `requestUpdate` does not access or return the * `updateComplete` promise. This promise can be overridden and is therefore * not free to access. */ requestUpdateInternal(name, oldValue, options) { let shouldRequestUpdate = true; // If we have a property key, perform property update steps. if (name !== undefined) { const ctor = this.constructor; options = options || ctor.getPropertyOptions(name); if (ctor._valueHasChanged(this[name], oldValue, options.hasChanged)) { 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._updateState & STATE_IS_REFLECTING_TO_PROPERTY)) { 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._hasRequestedUpdate && shouldRequestUpdate) { this._updatePromise = this._enqueueUpdate(); } } /** * 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 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. Returns the `updateComplete` Promise which is resolved * when the update completes. * * @param name {PropertyKey} (optional) name of requesting property * @param oldValue {any} (optional) old value of requesting property * @returns {Promise} A Promise that is resolved when the update completes. */ requestUpdate(name, oldValue) { this.requestUpdateInternal(name, oldValue); return this.updateComplete; } /** * Sets up the element to asynchronously update. */ async _enqueueUpdate() { this._updateState = this._updateState | STATE_UPDATE_REQUESTED; try { // Ensure any previous update has resolved before updating. // This `await` also ensures that property changes are batched. await this._updatePromise; } catch (e) { // Ignore any previous errors. We only care that the previous cycle is // done. Any error should have been handled in the previous update. } const result = this.performUpdate(); // If `performUpdate` 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._hasRequestedUpdate; } get _hasRequestedUpdate() { return (this._updateState & STATE_UPDATE_REQUESTED); } get hasUpdated() { return (this._updateState & STATE_HAS_UPDATED); } /** * Performs an element update. Note, if an exception is thrown during the * update, `firstUpdated` and `updated` will not be called. * * You can override this method to change the timing of updates. If this * method is overridden, `super.performUpdate()` must be called. * * For instance, to schedule updates to occur just before the next frame: * * ``` * protected async performUpdate(): Promise<unknown> { * await new Promise((resolve) => requestAnimationFrame(() => resolve())); * super.performUpdate(); * } * ``` */ performUpdate() { // 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._hasRequestedUpdate) { return; } // Mixin instance properties once, if they exist. if (this._instanceProperties) { this._applyInstanceProperties(); } let shouldUpdate = false; const changedProperties = this._changedProperties; try { shouldUpdate = this.shouldUpdate(changedProperties); if (shouldUpdate) { 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; } if (shouldUpdate) { if (!(this._updateState & STATE_HAS_UPDATED)) { this._updateState = this._updateState | STATE_HAS_UPDATED; this.firstUpdated(changedProperties); } this.updated(changedProperties); } } _markUpdated() { this._changedProperties = new Map(); this._updateState = this._updateState & ~STATE_UPDATE_REQUESTED; } /** * 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. * * @returns {Promise} The Promise returns a boolean that indicates if the * update resolved without triggering another update. */ 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: * * class MyElement extends LitElement { * async _getUpdateComplete() { * await super._getUpdateComplete(); * await this._myChild.updateComplete; * } * } */ _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 */ 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 */ update(_changedProperties) { if (this._reflectingProperties !== undefined && this._reflectingProperties.size > 0) { // 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 */ updated(_changedProperties) { } /** * Invoked when the element is first updated. Implement to perform one time * work on the element after update. * * 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 */ firstUpdated(_changedProperties) { } } _a$c = finalized; /** * Marks class as having finished creating properties. */ UpdatingElement[_a$c] = true; /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at * http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at * http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ const standardProperty = (options, element) => { // When decorating an accessor, pass it through and add property metadata. // Note, the `hasOwnProperty` check in `createProperty` ensures we don't // stomp over the user's accessor. if (element.kind === 'method' && element.descriptor && !('value' in element.descriptor)) { return Object.assign(Object.assign({}, element), { finisher(clazz) { clazz.createProperty(element.key, options); } }); } else { // createProperty() takes care of defining the property, but we still // must return some kind of descriptor, so return a descriptor for an // unused prototype field. The finisher calls createProperty(). return { kind: 'field', key: Symbol(), placement: 'own', descriptor: {}, // When @babel/plugin-proposal-decorators implements initializers, // do this instead of the initializer below. See: // https://github.com/babel/babel/issues/9260 extras: [ // { // kind: 'initializer', // placement: 'own', // initializer: descriptor.initializer, // } // ], initializer() { if (typeof element.initializer === 'function') { this[element.key] = element.initializer.call(this); } }, finisher(clazz) { clazz.createProperty(element.key, options); } }; } }; const legacyProperty = (options, proto, name) => { proto.constructor .createProperty(name, options); }; /** * A property decorator which creates a LitElement property which reflects a * corresponding attribute value. A [[`PropertyDeclaration`]] may optionally be * supplied to configure property features. * * This decorator should only be used for public fields. Private or protected * fields should use the [[`internalProperty`]] decorator. * * @example * ```ts * class MyElement { * @property({ type: Boolean }) * clicked = false; * } * ``` * @category Decorator * @ExportDecoratedItems */ function property(options) { // tslint:disable-next-line:no-any decorator return (protoOrDescriptor, name) => (name !== undefined) ? legacyProperty(options, protoOrDescriptor, name) : standardProperty(options, protoOrDescriptor); } /** @license Copyright (c) 2019 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ /** * Whether the current browser supports `adoptedStyleSheets`. */ (window.ShadowRoot) && (window.ShadyCSS === undefined || window.ShadyCSS.nativeShadow) && ('adoptedStyleSheets' in Document.prototype) && ('replace' in CSSStyleSheet.prototype); /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at * http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at * http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ // IMPORTANT: do not change the property name or the assignment expression. // This line will be used in regexes to search for LitElement usage. // TODO(justinfagnani): inject version number at build time (window['litElementVersions'] || (window['litElementVersions'] = [])) .push('2.4.0'); /* @license * Copyright 2019 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // NOTE(cdata): The HAS_WEBXR_* constants can be enabled in Chrome by turning on // the appropriate flags. However, just because we have the API does not // guarantee that AR will work. const HAS_WEBXR_DEVICE_API = navigator.xr != null && self.XRSession != null && navigator.xr.isSessionSupported != null; const HAS_WEBXR_HIT_TEST_API = HAS_WEBXR_DEVICE_API && self.XRSession.prototype.requestHitTestSource; const HAS_RESIZE_OBSERVER = self.ResizeObserver != null; const HAS_INTERSECTION_OBSERVER = self.IntersectionObserver != null; const IS_WEBXR_AR_CANDIDATE = HAS_WEBXR_HIT_TEST_API; (() => { const userAgent = navigator.userAgent || navigator.vendor || self.opera; let check = false; // eslint-disable-next-line if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i .test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i .test(userAgent.substr(0, 4))) { check = true; } return check; })(); /\bCrOS\b/.test(navigator.userAgent); // Disabling offscreen canvas for now because it is slower and has bugs relating // to janky updates and out of sync frames. const USE_OFFSCREEN_CANVAS = false; // Boolean((self as any).OffscreenCanvas) && // Boolean((self as any).OffscreenCanvas.prototype.transferToImageBitmap) && // !IS_CHROMEOS; // TODO(elalish): file a bug on inverted renders const IS_ANDROID = /android/i.test(navigator.userAgent); // Prior to iOS 13, detecting iOS Safari was relatively straight-forward. // As of iOS 13, Safari on iPad (in its default configuration) reports the same // user-agent string as Safari on desktop MacOS. Strictly speaking, we only care // about iOS for the purposes if selecting for cases where Quick Look is known // to be supported. However, for API correctness purposes, we must rely on // known, detectable signals to distinguish iOS Safari from MacOS Safari. At the // time of this writing, there are no non-iOS/iPadOS Apple devices with // multi-touch displays. // @see https://stackoverflow.com/questions/57765958/how-to-detect-ipad-and-ipad-os-version-in-ios-13-and-up // @see https://forums.developer.apple.com/thread/119186 // @see https://github.com/google/model-viewer/issues/758 const IS_IOS = (/iPad|iPhone|iPod/.test(navigator.userAgent) && !self.MSStream) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); const IS_AR_QUICKLOOK_CANDIDATE = (() => { const tempAnchor = document.createElement('a'); return Boolean(tempAnchor.relList && tempAnchor.relList.supports && tempAnchor.relList.supports('ar')); })(); // @see https://developer.chrome.com/multidevice/user-agent /Safari\//.test(navigator.userAgent); const IS_FIREFOX = /firefox/i.test(navigator.userAgent); const IS_OCULUS = /OculusBrowser/.test(navigator.userAgent); IS_IOS && /CriOS\//.test(navigator.userAgent); const IS_SCENEVIEWER_CANDIDATE = IS_ANDROID && !IS_FIREFOX && !IS_OCULUS; /* @license * Copyright 2019 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var CloseIcon = ` <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#000000"> <!-- NOTE(cdata): This SVG filter is a stop-gap until we can implement support for dynamic re-coloring of UI components --> <defs> <filter id="drop-shadow" x="-100%" y="-100%" width="300%" height="300%"> <feGaussianBlur in="SourceAlpha" stdDeviation="1"/> <feOffset dx="0" dy="0" result="offsetblur"/> <feFlood flood-color="#000000"/> <feComposite in2="offsetblur" operator="in"/> <feMerge> <feMergeNode/> <feMergeNode in="SourceGraphic"/> </feMerge> </filter> </defs> <path filter="url(#drop-shadow)" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/> <path d="M0 0h24v24H0z" fill="none"/> </svg>`; /* @license * Copyright 2019 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var ControlsPrompt = ` <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="36"> <defs> <path id="A" d="M.001.232h24.997V36H.001z" /> </defs> <g transform="translate(-11 -4)" fill="none" fill-rule="evenodd"> <path fill-opacity="0" fill="#fff" d="M0 0h44v44H0z" /> <g transform="translate(11 3)"> <path d="M8.733 11.165c.04-1.108.766-2.027 1.743-2.307a2.54 2.54 0 0 1 .628-.089c.16 0 .314.017.463.044 1.088.2 1.9 1.092 1.9 2.16v8.88h1.26c2.943-1.39 5-4.45 5-8.025a9.01 9.01 0 0 0-1.9-5.56l-.43-.5c-.765-.838-1.683-1.522-2.712-2-1.057-.49-2.226-.77-3.46-.77s-2.4.278-3.46.77c-1.03.478-1.947 1.162-2.71 2l-.43.5a9.01 9.01 0 0 0-1.9 5.56 9.04 9.04 0 0 0 .094 1.305c.03.21.088.41.13.617l.136.624c.083.286.196.56.305.832l.124.333a8.78 8.78 0 0 0 .509.953l.065.122a8.69 8.69 0 0 0 3.521 3.191l1.11.537v-9.178z" fill-opacity=".5" fill="#e4e4e4" /> <path d="M22.94 26.218l-2.76 7.74c-.172.485-.676.8-1.253.8H12.24c-1.606 0-3.092-.68-3.98-1.82-1.592-2.048-3.647-3.822-6.11-5.27-.095-.055-.15-.137-.152-.23-.004-.1.046-.196.193-.297.56-.393 1.234-.6 1.926-.6a3.43 3.43 0 0 1 .691.069l4.922.994V10.972c0-.663.615-1.203 1.37-1.203s1.373.54 1.373 1.203v9.882h2.953c.273 0 .533.073.757.21l6.257 3.874c.027.017.045.042.07.06.41.296.586.77.426 1.22M4.1 16.614c-.024-.04-.042-.083-.065-.122a8.69 8.69 0 0 1-.509-.953c-.048-.107-.08-.223-.124-.333l-.305-.832c-.058-.202-.09-.416-.136-.624l-.13-.617a9.03 9.03 0 0 1-.094-1.305c0-2.107.714-4.04 1.9-5.56l.43-.5c.764-.84 1.682-1.523 2.71-2 1.058-.49 2.226-.77 3.46-.77s2.402.28 3.46.77c1.03.477 1.947 1.16 2.712 2l.428.5a9 9 0 0 1 1.901 5.559c0 3.577-2.056 6.636-5 8.026h-1.26v-8.882c0-1.067-.822-1.96-1.9-2.16-.15-.028-.304-.044-.463-.044-.22 0-.427.037-.628.09-.977.28-1.703 1.198-1.743 2.306v9.178l-1.11-.537C6.18 19.098 4.96 18 4.1 16.614M22.97 24.09l-6.256-3.874c-.102-.063-.218-.098-.33-.144 2.683-1.8 4.354-4.855 4.354-8.243 0-.486-.037-.964-.104-1.43a9.97 9.97 0 0 0-1.57-4.128l-.295-.408-.066-.092a10.05 10.05 0 0 0-.949-1.078c-.342-.334-.708-.643-1.094-.922-1.155-.834-2.492-1.412-3.94-1.65l-.732-.088-.748-.03a9.29 9.29 0 0 0-1.482.119c-1.447.238-2.786.816-3.94 1.65a9.33 9.33 0 0 0-.813.686 9.59 9.59 0 0 0-.845.877l-.385.437-.36.5-.288.468-.418.778-.04.09c-.593 1.28-.93 2.71-.93 4.222 0 3.832 2.182 7.342 5.56 8.938l1.437.68v4.946L5 25.64a4.44 4.44 0 0 0-.888-.086c-.017 0-.034.003-.05.003-.252.004-.503.033-.75.08a5.08 5.08 0 0 0-.237.056c-.193.046-.382.107-.568.18-.075.03-.15.057-.225.1-.25.114-.494.244-.723.405a1.31 1.31 0 0 0-.566 1.122 1.28 1.28 0 0 0 .645 1.051C4 29.925 5.96 31.614 7.473 33.563a5.06 5.06 0 0 0 .434.491c1.086 1.082 2.656 1.713 4.326 1.715h6.697c.748-.001 1.43-.333 1.858-.872.142-.18.256-.38.336-.602l2.757-7.74c.094-.26.13-.53.112-.794s-.088-.52-.203-.76a2.19 2.19 0 0 0-.821-.91" fill-opacity=".6" fill="#000" /> <path d="M22.444 24.94l-6.257-3.874a1.45 1.45 0 0 0-.757-.211h-2.953v-9.88c0-.663-.616-1.203-1.373-1.203s-1.37.54-1.37 1.203v16.643l-4.922-.994a3.44 3.44 0 0 0-.692-.069 3.35 3.35 0 0 0-1.925.598c-.147.102-.198.198-.194.298.004.094.058.176.153.23 2.462 1.448 4.517 3.22 6.11 5.27.887 1.14 2.373 1.82 3.98 1.82h6.686c.577 0 1.08-.326 1.253-.8l2.76-7.74c.16-.448-.017-.923-.426-1.22-.025-.02-.043-.043-.07-.06z" fill="#fff" /> <g transform="translate(0 .769)"> <mask id="B" fill="#fff"> <use xlink:href="#A" /> </mask> <path d="M23.993 24.992a1.96 1.96 0 0 1-.111.794l-2.758 7.74c-.08.22-.194.423-.336.602-.427.54-1.11.87-1.857.872h-6.698c-1.67-.002-3.24-.633-4.326-1.715-.154-.154-.3-.318-.434-.49C5.96 30.846 4 29.157 1.646 27.773c-.385-.225-.626-.618-.645-1.05a1.31 1.31 0 0 1 .566-1.122 4.56 4.56 0 0 1 .723-.405l.225-.1a4.3 4.3 0 0 1 .568-.18l.237-.056c.248-.046.5-.075.75-.08.018 0 .034-.003.05-.003.303-.001.597.027.89.086l3.722.752V20.68l-1.436-.68c-3.377-1.596-5.56-5.106-5.56-8.938 0-1.51.336-2.94.93-4.222.015-.03.025-.06.04-.09.127-.267.268-.525.418-.778.093-.16.186-.316.288-.468.063-.095.133-.186.2-.277L3.773 5c.118-.155.26-.29.385-.437.266-.3.544-.604.845-.877a9.33 9.33 0 0 1 .813-.686C6.97 2.167 8.31 1.59 9.757 1.35a9.27 9.27 0 0 1 1.481-.119 8.82 8.82 0 0 1 .748.031c.247.02.49.05.733.088 1.448.238 2.786.816 3.94 1.65.387.28.752.588 1.094.922a9.94 9.94 0 0 1 .949 1.078l.066.092c.102.133.203.268.295.408a9.97 9.97 0 0 1 1.571 4.128c.066.467.103.945.103 1.43 0 3.388-1.67 6.453-4.353 8.243.11.046.227.08.33.144l6.256 3.874c.37.23.645.55.82.9.115.24.185.498.203.76m.697-1.195c-.265-.55-.677-1.007-1.194-1.326l-5.323-3.297c2.255-2.037 3.564-4.97 3.564-8.114 0-2.19-.637-4.304-1.84-6.114-.126-.188-.26-.37-.4-.552-.645-.848-1.402-1.6-2.252-2.204C15.472.91 13.393.232 11.238.232A10.21 10.21 0 0 0 5.23 2.19c-.848.614-1.606 1.356-2.253 2.205-.136.18-.272.363-.398.55C1.374 6.756.737 8.87.737 11.06c0 4.218 2.407 8.08 6.133 9.842l.863.41v3.092l-2.525-.51c-.356-.07-.717-.106-1.076-.106a5.45 5.45 0 0 0-3.14.996c-.653.46-1.022 1.202-.99 1.983a2.28 2.28 0 0 0 1.138 1.872c2.24 1.318 4.106 2.923 5.543 4.772 1.26 1.62 3.333 2.59 5.55 2.592h6.698c1.42-.001 2.68-.86 3.134-2.138l2.76-7.74c.272-.757.224-1.584-.134-2.325" fill-opacity=".05" fill="#000" mask="url(#B)" /> </g> </g> </g> </svg>`; /* @license * Copyright 2019 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless