UNPKG

@open-wc/scoped-elements

Version:
92 lines (79 loc) 2.85 kB
import { dedupeMixin } from '@open-wc/dedupe-mixin'; /** * @typedef {import('./types.js').ScopedElementsHost} ScopedElementsHost * @typedef {import('./types.js').ScopedElementsMap} ScopedElementsMap */ const version = '3.0.0'; const versions = window.scopedElementsVersions || (window.scopedElementsVersions = []); if (!versions.includes(version)) { versions.push(version); } /** * @template {import('./types.js').Constructor<HTMLElement>} T * @param {T} superclass * @return {T & import('./types.js').Constructor<ScopedElementsHost>} */ const ScopedElementsMixinImplementation = superclass => /** @type {ScopedElementsHost} */ class ScopedElementsHost extends superclass { /** * Obtains the scoped elements definitions map if specified. * * @type {ScopedElementsMap=} */ static scopedElements; static get scopedElementsVersion() { return version; } /** @type {CustomElementRegistry=} */ static __registry; /** * Obtains the CustomElementRegistry associated to the ShadowRoot. * * @returns {CustomElementRegistry=} */ get registry() { return /** @type {typeof ScopedElementsHost} */ (this.constructor).__registry; } /** * Set the CustomElementRegistry associated to the ShadowRoot * * @param {CustomElementRegistry} registry */ set registry(registry) { /** @type {typeof ScopedElementsHost} */ (this.constructor).__registry = registry; } /** * @param {ShadowRootInit} options * @returns {ShadowRoot} */ attachShadow(options) { const { scopedElements } = /** @type {typeof ScopedElementsHost} */ (this.constructor); const shouldCreateRegistry = !this.registry || // @ts-ignore (this.registry === this.constructor.__registry && !Object.prototype.hasOwnProperty.call(this.constructor, '__registry')); /** * Create a new registry if: * - the registry is not defined * - this class doesn't have its own registry *AND* has no shared registry * This is important specifically for superclasses/inheritance */ if (shouldCreateRegistry) { this.registry = new CustomElementRegistry(); for (const [tagName, klass] of Object.entries(scopedElements ?? {})) { this.registry.define(tagName, klass); } } return super.attachShadow({ ...options, // The polyfill currently expects the registry to be passed as `customElements` customElements: this.registry, // But the proposal has moved forward, and renamed it to `registry` // For backwards compatibility, we pass it as both registry: this.registry, }); } }; export const ScopedElementsMixin = dedupeMixin(ScopedElementsMixinImplementation);