/** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ import { ElementInternalsShim } from './lib/element-internals.js'; export { ariaMixinAttributes, ElementInternals, HYDRATE_INTERNALS_ATTR_PREFIX, } from './lib/element-internals.js'; const attributes = new WeakMap(); const attributesForElement = (element) => { let attrs = attributes.get(element); if (attrs === undefined) { attributes.set(element, (attrs = new Map())); } return attrs; }; // The typings around the exports below are a little funky: // // 1. We want the `name` of the shim classes to match the real ones at runtime, // hence e.g. `class Element`. // 2. We can't shadow the global types with a simple class declaration, because // then we can't reference the global types for casting, hence e.g. // `const ElementShim = class Element`. // 3. We want to export the classes typed as the real ones, hence e.g. // `const ElementShimWithRealType = ElementShim as object as typeof Element;`. // 4. We want the exported names to match the real ones, hence e.g. // `export {ElementShimWithRealType as Element}`. const ElementShim = class Element { constructor() { this.__shadowRootMode = null; this.__shadowRoot = null; this.__internals = null; } get attributes() { return Array.from(attributesForElement(this)).map(([name, value]) => ({ name, value, })); } get shadowRoot() { if (this.__shadowRootMode === 'closed') { return null; } return this.__shadowRoot; } setAttribute(name, value) { // Emulate browser behavior that silently casts all values to string. E.g. // `42` becomes `"42"` and `{}` becomes `"[object Object]""`. attributesForElement(this).set(name, String(value)); } removeAttribute(name) { attributesForElement(this).delete(name); } toggleAttribute(name, force) { // Steps reference https://dom.spec.whatwg.org/#dom-element-toggleattribute if (this.hasAttribute(name)) { // Step 5 if (force === undefined || !force) { this.removeAttribute(name); return false; } } else { // Step 4 if (force === undefined || force) { // Step 4.1 this.setAttribute(name, ''); return true; } else { // Step 4.2 return false; } } // Step 6 return true; } hasAttribute(name) { return attributesForElement(this).has(name); } attachShadow(init) { const shadowRoot = { host: this }; this.__shadowRootMode = init.mode; if (init && init.mode === 'open') { this.__shadowRoot = shadowRoot; } return shadowRoot; } attachInternals() { if (this.__internals !== null) { throw new Error(`Failed to execute 'attachInternals' on 'HTMLElement': ` + `ElementInternals for the specified element was already attached.`); } const internals = new ElementInternalsShim(this); this.__internals = internals; return internals; } getAttribute(name) { const value = attributesForElement(this).get(name); return value ?? null; } }; const ElementShimWithRealType = ElementShim; export { ElementShimWithRealType as Element }; const HTMLElementShim = class HTMLElement extends ElementShim { }; const HTMLElementShimWithRealType = HTMLElementShim; export { HTMLElementShimWithRealType as HTMLElement }; const CustomElementRegistryShim = class CustomElementRegistry { constructor() { this.__definitions = new Map(); } define(name, ctor) { if (this.__definitions.has(name)) { if (process.env.NODE_ENV === 'development') { console.warn(`'CustomElementRegistry' already has "${name}" defined. ` + `This may have been caused by live reload or hot module ` + `replacement in which case it can be safely ignored.\n` + `Make sure to test your application with a production build as ` + `repeat registrations will throw in production.`); } else { throw new Error(`Failed to execute 'define' on 'CustomElementRegistry': ` + `the name "${name}" has already been used with this registry`); } } this.__definitions.set(name, { ctor, // Note it's important we read `observedAttributes` in case it is a getter // with side-effects, as is the case in Lit, where it triggers class // finalization. // // TODO(aomarks) To be spec compliant, we should also capture the // registration-time lifecycle methods like `connectedCallback`. For them // to be actually accessible to e.g. the Lit SSR element renderer, though, // we'd need to introduce a new API for accessing them (since `get` only // returns the constructor). observedAttributes: ctor.observedAttributes ?? [], }); } get(name) { const definition = this.__definitions.get(name); return definition?.ctor; } }; const CustomElementRegistryShimWithRealType = CustomElementRegistryShim; export { CustomElementRegistryShimWithRealType as CustomElementRegistry }; export const customElements = new CustomElementRegistryShimWithRealType(); //# sourceMappingURL=index.js.map