Skip to content

Commit d73ced7

Browse files
committed
Move CustomElement.define call to Astro layout in all existing web components, use defineCustomElement helper method consistently
1 parent 4e39061 commit d73ced7

22 files changed

Lines changed: 87 additions & 63 deletions

File tree

src/components/CallToAction/Newsletter/client/__tests__/index.spec.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('NewsletterFormElement web component', () => {
1616
let container: AstroContainer
1717
let newsletterElement: NewsletterFormElementInstance
1818
let windowInstance: Window
19-
let NewsletterFormElementCtor: NewsletterClientModule['NewsletterFormElement'] | undefined
19+
let registerNewsletterFormWebComponent: NewsletterClientModule['registerNewsletterFormWebComponent'] | undefined
2020
let fetchMock: ReturnType<typeof vi.fn>
2121

2222
const defineGlobalProperty = (key: string, value: unknown) => {
@@ -56,7 +56,11 @@ describe('NewsletterFormElement web component', () => {
5656
beforeAll(async () => {
5757
windowInstance = new Window()
5858
applyWindowGlobals(windowInstance)
59-
;({ NewsletterFormElement: NewsletterFormElementCtor } = await import('@components/CallToAction/Newsletter/client'))
59+
const clientModule = await import('@components/CallToAction/Newsletter/client')
60+
registerNewsletterFormWebComponent = clientModule.registerNewsletterFormWebComponent
61+
if (!registerNewsletterFormWebComponent) {
62+
throw new Error('registerNewsletterFormWebComponent is unavailable')
63+
}
6064
})
6165

6266
beforeEach(async () => {
@@ -67,23 +71,19 @@ describe('NewsletterFormElement web component', () => {
6771
const html = await container.renderToString(NewsletterFixture)
6872
const domParser = new windowInstance.DOMParser()
6973
const doc = domParser.parseFromString(html, 'text/html')
74+
75+
if (!registerNewsletterFormWebComponent) {
76+
throw new Error('registerNewsletterFormWebComponent did not initialize')
77+
}
78+
79+
registerNewsletterFormWebComponent()
7080
windowInstance.document.body.innerHTML = doc.body?.innerHTML ?? ''
7181

7282
const root = windowInstance.document.querySelector('newsletter-form') as NewsletterFormElementInstance | null
7383
if (!root) {
7484
throw new Error('Failed to locate <newsletter-form> in rendered fixture')
7585
}
7686

77-
if (!windowInstance.customElements.get('newsletter-form')) {
78-
if (!NewsletterFormElementCtor) {
79-
throw new Error('NewsletterFormElement failed to load before tests executed')
80-
}
81-
windowInstance.customElements.define(
82-
'newsletter-form',
83-
NewsletterFormElementCtor as unknown as CustomElementConstructor
84-
)
85-
}
86-
8787
newsletterElement = root
8888
newsletterElement.initialize()
8989
})

src/components/CallToAction/Newsletter/client/index.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { LitElement } from 'lit'
88
import { addScriptBreadcrumb, ClientScriptError } from '@components/scripts/errors'
99
import { handleScriptError } from '@components/scripts/errors/handler'
1010
import { getNewsletterElements } from './selectors'
11+
import { defineCustomElement } from '@components/scripts/utils'
1112

1213
/**
1314
* Newsletter Form Custom Element (Lit-based)
@@ -44,11 +45,18 @@ export class NewsletterFormElement extends LitElement {
4445
const context = { scriptName: 'NewsletterFormElement', operation: 'connectedCallback' }
4546
addScriptBreadcrumb(context)
4647

47-
// Wait for DOM to be ready before initializing
48+
const scheduleInitialization = () => {
49+
queueMicrotask(() => this.initialize())
50+
}
51+
4852
if (document.readyState === 'loading') {
49-
document.addEventListener('DOMContentLoaded', () => this.initialize())
53+
const handleDomReady = () => {
54+
document.removeEventListener('DOMContentLoaded', handleDomReady)
55+
scheduleInitialization()
56+
}
57+
document.addEventListener('DOMContentLoaded', handleDomReady)
5058
} else {
51-
this.initialize()
59+
scheduleInitialization()
5260
}
5361
}
5462

@@ -315,8 +323,6 @@ export class NewsletterFormElement extends LitElement {
315323
}
316324
}
317325

318-
// Register the custom element
319-
if (!customElements.get('newsletter-form')) {
320-
customElements.define('newsletter-form', NewsletterFormElement)
321-
}
326+
export const registerNewsletterFormWebComponent = (tagName = 'newsletter-form') =>
327+
defineCustomElement(tagName, NewsletterFormElement)
322328

src/components/CallToAction/Newsletter/index.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,6 @@ const {
149149
</newsletter-form>
150150

151151
<script>
152-
import '@components/CallToAction/Newsletter/client'
153-
// Web component auto-initializes when custom element is defined
152+
import { registerNewsletterFormWebComponent } from '@components/CallToAction/Newsletter/client'
153+
registerNewsletterFormWebComponent()
154154
</script>

src/components/Carousel/client/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Autoplay from 'embla-carousel-autoplay'
33
import { addButtonEventListeners } from '@components/scripts/elementListeners'
44
import { addScriptBreadcrumb, ClientScriptError } from '@components/scripts/errors'
55
import { handleScriptError } from '@components/scripts/errors/handler'
6+
import { defineCustomElement } from '@components/scripts/utils'
67

78
const SCRIPT_NAME = 'CarouselElement'
89

@@ -297,6 +298,7 @@ declare global {
297298
}
298299
}
299300

300-
if (typeof window !== 'undefined' && !customElements.get('carousel-slider')) {
301-
customElements.define('carousel-slider', CarouselElement)
301+
export const registerCarouselWebComponent = (tagName = 'carousel-slider') => {
302+
if (typeof window === 'undefined') return
303+
defineCustomElement(tagName, CarouselElement)
302304
}

src/components/Carousel/index.astro

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,5 +203,6 @@ if (limit) {
203203
}
204204

205205
<script>
206-
import '@components/Carousel/client'
206+
import { registerCarouselWebComponent } from '@components/Carousel/client'
207+
registerCarouselWebComponent()
207208
</script>

src/components/Consent/Banner/client/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
} from '@components/Consent/Banner/client/selectors'
2121
import { addScriptBreadcrumb } from '@components/scripts/errors'
2222
import { handleScriptError } from '@components/scripts/errors/handler'
23+
import { defineCustomElement } from '@components/scripts/utils'
2324

2425
/**
2526
* Consent Banner Custom Element
@@ -359,7 +360,5 @@ export class ConsentBannerElement extends LitElement {
359360
}
360361
}
361362

362-
// Register the custom element
363-
if (!customElements.get('consent-banner')) {
364-
customElements.define('consent-banner', ConsentBannerElement)
365-
}
363+
export const registerConsentBannerWebComponent = (tagName = 'consent-banner') =>
364+
defineCustomElement(tagName, ConsentBannerElement)

src/components/Consent/Banner/index.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ import CookieSvg from '@assets/images/site/cookie.svg'
6767
</consent-banner>
6868

6969
<script>
70-
// Import the Web Component - it will auto-register
71-
import '@components/Consent/Banner/client'
70+
import { registerConsentBannerWebComponent } from '@components/Consent/Banner/client'
7271
import { initConsentSideEffects } from '@components/scripts/store'
72+
registerConsentBannerWebComponent()
7373

7474
// Initialize cookie consent side effects with Astro View Transitions
7575
document.addEventListener('astro:page-load', () => {

src/components/Consent/Preferences/client/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
getAllowAllBtn,
2020
getSavePreferencesBtn,
2121
} from '@components/Consent/Preferences/client/selectors'
22+
import { defineCustomElement } from '@components/scripts/utils'
2223

2324
/**
2425
* Consent Preferences web component
@@ -302,7 +303,5 @@ export const showConsentCustomizeModal = (): void => {
302303
modal.style.display = 'flex'
303304
}
304305

305-
// Register the custom element (with guard against duplicate registration)
306-
if (!customElements.get('consent-preferences')) {
307-
customElements.define('consent-preferences', ConsentPreferencesElement)
308-
}
306+
export const registerConsentPreferencesWebComponent = (tagName = 'consent-preferences') =>
307+
defineCustomElement(tagName, ConsentPreferencesElement)

src/components/Consent/Preferences/index.astro

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,5 +196,6 @@ import logoSvg from '@assets/images/site/logo.svg'
196196

197197
<!-- Privacy Preferences Management Script -->
198198
<script>
199-
import '@components/Consent/Preferences/client'
199+
import { registerConsentPreferencesWebComponent } from '@components/Consent/Preferences/client'
200+
registerConsentPreferencesWebComponent()
200201
</script>

src/components/Footer/client/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { LitElement } from 'lit'
66
import { getHireMeAnchorElement } from '@components/Footer/client/selectors'
77
import { addScriptBreadcrumb } from '@components/scripts/errors'
88
import { handleScriptError } from '@components/scripts/errors/handler'
9+
import { defineCustomElement } from '@components/scripts/utils'
910

1011
class FooterElement extends LitElement {
1112
private hireMeAnchor: HTMLAnchorElement | null = null
@@ -54,8 +55,7 @@ class FooterElement extends LitElement {
5455
}
5556
}
5657

57-
if (!customElements.get('site-footer')) {
58-
customElements.define('site-footer', FooterElement)
59-
}
58+
export const registerFooterWebComponent = (tagName = 'site-footer') =>
59+
defineCustomElement(tagName, FooterElement)
6060

6161
export { FooterElement }

0 commit comments

Comments
 (0)