From 72491e1c5f2278fb5e19cacc8d799dab92329f95 Mon Sep 17 00:00:00 2001 From: Markus Hesper Date: Thu, 4 Sep 2025 21:42:46 +0200 Subject: [PATCH 1/3] feat(ejs): render and attach shadowroot in the same tick. --- src/TemplateElement.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/TemplateElement.js b/src/TemplateElement.js index b188c7e..5a983d3 100644 --- a/src/TemplateElement.js +++ b/src/TemplateElement.js @@ -31,7 +31,6 @@ class TemplateElement extends StyledElement { * This will attach a shadow DOM if the element is supposed to render in shadow DOM. */ connectedCallback() { - if (this._options.shadowRender && !this.shadowRoot) this.attachShadow({ mode: 'open' }); super.connectedCallback(); } @@ -48,6 +47,12 @@ class TemplateElement extends StyledElement { * @param {PropertyUpdateOptions} options */ update(options) { + let firstRender = this._options.shadowRender && !this.shadowRoot; + if (firstRender) { + this.attachShadow({ mode: 'open' }); + // adopt stylesheets + this.adoptStyleSheets(); + } this.renderTemplate(); super.update(options); } From 2b37d3a123b7d0f220cade83791f0b0058b54a0d Mon Sep 17 00:00:00 2001 From: quarkus Date: Fri, 5 Sep 2025 21:24:34 +0200 Subject: [PATCH 2/3] feat(ejs): move attach check to the actual renderTemplate function --- src/TemplateElement.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/TemplateElement.js b/src/TemplateElement.js index 5a983d3..c67457b 100644 --- a/src/TemplateElement.js +++ b/src/TemplateElement.js @@ -28,7 +28,6 @@ class TemplateElement extends StyledElement { /** * Overrides the native `connectedCallback` of the HTMLElement to set up and initialize our element. - * This will attach a shadow DOM if the element is supposed to render in shadow DOM. */ connectedCallback() { super.connectedCallback(); @@ -47,20 +46,22 @@ class TemplateElement extends StyledElement { * @param {PropertyUpdateOptions} options */ update(options) { - let firstRender = this._options.shadowRender && !this.shadowRoot; - if (firstRender) { - this.attachShadow({ mode: 'open' }); - // adopt stylesheets - this.adoptStyleSheets(); - } this.renderTemplate(); super.update(options); } /** * Render the template to the root + * This will attach a shadow DOM if the element is supposed to render in shadow DOM. */ renderTemplate() { + let firstRender = this._options.shadowRender && !this.shadowRoot; + if (firstRender) { + this.attachShadow({ mode: 'open' }); + // adopt stylesheets + this.adoptStyleSheets(); + } + const template = this._template || this.template(); render(template, this.getRoot()); } From cd677d19e693c48232adf20272bf6b3bf99e5c64 Mon Sep 17 00:00:00 2001 From: quarkus Date: Fri, 5 Sep 2025 21:40:08 +0200 Subject: [PATCH 3/3] feat(ejs): moved external style initialization to a dedicated function (initStyleAdoption) which makes things hopefully better to understand. also removed the code from StyledElements connected as it needs a shadowRoot anyways to actually make sense. --- src/StyledElement.js | 31 ++++++++++++++++++++----------- src/TemplateElement.js | 6 +++--- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/StyledElement.js b/src/StyledElement.js index af2b93b..9ab37b7 100644 --- a/src/StyledElement.js +++ b/src/StyledElement.js @@ -39,17 +39,6 @@ class StyledElement extends BaseElement { return cssStyleSheet; }); } - - if (supportsAdoptingStyleSheets() && this._options.shadowRender) { - // adopting does only make sense in shadow dom. Fall back to append for light elements - this.adoptStyleSheets(); - - if (this._options.adoptGlobalStyles !== false) { - globalStylesStore.subscribe(() => { - this.adoptStyleSheets(); - }); - } - } } /** @@ -73,6 +62,26 @@ class StyledElement extends BaseElement { super.update(options); } + /** + * Start the adoption of external stylesheets + * adopt global styles from document + * subscribe to globalStylesStore for updates + * @returns { void } + */ + + initStyleAdoption() { + if (this._options.shadowRender && supportsAdoptingStyleSheets()) { + // adopting does only make sense in shadow dom. Fall back to append for light elements + this.adoptStyleSheets(); + + if (this._options.adoptGlobalStyles !== false) { + globalStylesStore.subscribe(() => { + this.adoptStyleSheets(); + }); + } + } + } + /** * Adopt stylesheets */ diff --git a/src/TemplateElement.js b/src/TemplateElement.js index c67457b..079c465 100644 --- a/src/TemplateElement.js +++ b/src/TemplateElement.js @@ -55,11 +55,11 @@ class TemplateElement extends StyledElement { * This will attach a shadow DOM if the element is supposed to render in shadow DOM. */ renderTemplate() { - let firstRender = this._options.shadowRender && !this.shadowRoot; + const firstRender = this._options.shadowRender && !this.shadowRoot; if (firstRender) { this.attachShadow({ mode: 'open' }); - // adopt stylesheets - this.adoptStyleSheets(); + // init external stylesheets + this.initStyleAdoption(); } const template = this._template || this.template();