- From: Nicolas Gilbert <notifications@github.com>
- Date: Thu, 09 Mar 2023 05:45:38 -0800
- To: WICG/webcomponents <webcomponents@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <WICG/webcomponents/issues/989@github.com>
I would like to propose a new `extends` option that could be passed on `new CustomElementRegistry()`. ```js const registry = new CustomElementRegistry({ extends: [registryA, registryB, registryC] }); ``` ## Use case As a developer, I am building a new component inside the `Products` page of my application. For this component, I will use components coming from the following scopes: - Global components for the entire app - Components only available to the `Products` section. - Components coming from my company's own `Core` library. - Components coming from 3rd party LibA and Lib2. In turn, those component may use other component libraries. Without registry extension, it may be quite a challenge to build a registry that define every dependencies correctly. With registry extension, I would do: ```js const registry = new CustomElementRegistry({ extends: [appRegistry, productsRegistry, coreRegistry, libARegistry, libBRegistry] }); ``` Conflicts between tag names (when 2 registries try to register the same name) would throw an error and would need to be handled manually. ## About scoped-constructor invocation I believe that registry extension could be a good alternative to forbidding constructor on scoped elements, when combined with the restriction that constructor are registered on a single registry. Extending a common registry would allow reuse of component without having to subclass over and over. The only cases where subclassing would be needed would be when registering some components on a different name than the default one. But this could be handle automatically and the new registry could be cached, see `getRegistry` helper in userland extensions below. ## Userland extensions You could see some userland ways to make life even easier, here are a few ideas. Good practice from libraries would be to export a `getRegistry` function with an optional prefix so conflicts could be avoided. ```js import { getRegistry as getLibARegistry } from 'lib-a'; import { getRegistry as getLibBRegistry } from 'lib-b'; const registry = new CustomElementRegistry({ extends: [ // We register lib-a using predefined names getLibARegistry(), // As lib-b conflicts with lib-a, we use a custom prefix for those elements. getLibBRegistry({ prefix: 'foobar' }) ] }); ``` Libraries could build their own registries of multiple sub-registries, for when only part of the library is imported. ```js const coreRegistry = new CustomElementRegistry({ extends: [ modalRegistry, formRegistry, gridRegistry, titleRegistry, /// Etc. ]; }); ``` Component could include a `getRegistry` static prop that would return a registry with the component's dependencies. Combines nicely with the [requiredElements proposal](https://github.com/WICG/webcomponents/issues/988). ```js // Could be improved with registry caching and automatic subclassing. function getRegistry({ prefix = DEFAULT_PREFIX } = {}) { const registry = new CustomElementRegistry({ extends: (this.requiredElements || []).map((Element) => Element.getRegistry({ prefix })) }); registry.define(`${prefix}-${this.baseName}`, this); return registry; } class ComponentA extends HTMLElement { static baseName 'a' static getRegistry = getRegistry; } class ComponentB extends HTMLElement { static baseName 'b' static requiredElements = [ComponentA]; static getRegistry = getRegistry; connectedCallback() { this.appendChild(new ComponentA()); } } ``` -- Reply to this email directly or view it on GitHub: https://github.com/WICG/webcomponents/issues/989 You are receiving this because you are subscribed to this thread. Message ID: <WICG/webcomponents/issues/989@github.com>
Received on Thursday, 9 March 2023 13:45:51 UTC