diff --git a/packages/scoped-elements/README.md b/packages/scoped-elements/README.md index 708ddb7c..2b9fe058 100644 --- a/packages/scoped-elements/README.md +++ b/packages/scoped-elements/README.md @@ -50,6 +50,8 @@ npm i --save @open-wc/scoped-elements > }; > } > ``` + > + > If you try to register the same element globally AND locally with the exact same name AND class instance it will reuse the global tag name and NOT scope it. 4. Use your components in your html. diff --git a/packages/scoped-elements/src/registerElement.js b/packages/scoped-elements/src/registerElement.js index 903247e0..e252e6e8 100644 --- a/packages/scoped-elements/src/registerElement.js +++ b/packages/scoped-elements/src/registerElement.js @@ -21,6 +21,26 @@ const defineElement = (tagName, klass, registry = customElements) => { addToGlobalTagsCache(tagName, klass); }; +/** + * Stores a lazy element in the cache to be used in future + * + * @param {string} tagName + * @param {CustomElementRegistry} registry + * @param {Map} tagsCache + * @returns {string} + */ +const storeLazyElementInCache = (tagName, registry, tagsCache) => { + const tag = createUniqueTag(tagName, registry); + + if (!tagsCache) { + throw new Error('Lazy scoped elements requires the use of tags cache'); + } + + tagsCache.set(tagName, tag); + + return tag; +}; + /** * Define a scoped custom element storing the scoped tag name in the cache * @@ -31,20 +51,22 @@ const defineElement = (tagName, klass, registry = customElements) => { */ const defineElementAndStoreInCache = (tagName, klass, tagsCache) => { const registry = customElements; - const tag = createUniqueTag(tagName, registry); - if (extendsHTMLElement(klass)) { - // @ts-ignore - // we extend it just in case the class has been defined manually - defineElement(tag, klass, registry); - } else { - if (!tagsCache) { - throw new Error('Lazy scoped elements requires the use of tags cache'); - } - - tagsCache.set(tagName, tag); + if (!extendsHTMLElement(klass)) { + return storeLazyElementInCache(tagName, registry, tagsCache); } + if (klass === customElements.get(tagName)) { + addToGlobalTagsCache(tagName, klass); + + return tagName; + } + + const tag = createUniqueTag(tagName, registry); + // @ts-ignore + // we extend it just in case the class has been defined manually + defineElement(tag, klass, registry); + return tag; }; diff --git a/packages/scoped-elements/test/ScopedElementsMixin.test.js b/packages/scoped-elements/test/ScopedElementsMixin.test.js index 1065c6d8..360141de 100644 --- a/packages/scoped-elements/test/ScopedElementsMixin.test.js +++ b/packages/scoped-elements/test/ScopedElementsMixin.test.js @@ -304,6 +304,37 @@ describe('ScopedElementsMixin', () => { await waitUntil(() => el.shadowRoot.children[1] instanceof LazyElement); }); + it('should reuse the global tag if defined with the same name and class reference', async () => { + class ItemA extends LitElement { + render() { + return html`
Item A
`; + } + } + + customElements.define('item-a', ItemA); + + const tag = defineCE( + class ContainerElement extends ScopedElementsMixin(LitElement) { + static get scopedElements() { + return { + ...super.scopedElements, + 'item-a': customElements.get('item-a'), + }; + } + + render() { + return html` `; + } + }, + ); + + const el = await fixture(`<${tag}>`); + const firstElement = el.shadowRoot.children[0]; + + expect(firstElement.tagName.toLowerCase()).to.be.equal('item-a'); + expect(firstElement).to.be.instanceof(ItemA); + }); + describe('getScopedTagName', () => { it('should return the scoped tag name for a registered element', async () => { const chars = `-|\\.|[0-9]|[a-z]`;