From b014988e0d77d02a9d255b17f0fcf36c920074cf Mon Sep 17 00:00:00 2001 From: Vincent Filby Date: Fri, 21 Aug 2026 20:46:34 -0700 Subject: [PATCH] Card: defer element registration until HA app boots (fixes HA 2026.8 registry race) HA 2026.8's frontend bundles the scoped-custom-element-registry polyfill, which replaces window.customElements with a fresh registry at app.js start. The card is loaded via extra_module_url, imported by the index page concurrently with app.js; with a warm cache it reliably defines on the native registry before the swap and customElements.get() then returns undefined -> "Custom element doesn't exist: shade-engine-card" on every dashboard (browsers and companion apps alike). Wait for customElements.whenDefined('home-assistant') and define on whatever registry is current at that point. Verified 10/10 registrations in headless Chromium against the live server (was ~1 in 6 failing cold, and consistently failing with a cached module). Bump to 0.5.1 so the ?v= cache-buster refreshes clients. Co-Authored-By: Claude Fable 5 --- custom_components/shade_engine/manifest.json | 2 +- .../shade_engine/www/shade-engine-card.js | 21 +++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/custom_components/shade_engine/manifest.json b/custom_components/shade_engine/manifest.json index 204fe26..a97d2f4 100644 --- a/custom_components/shade_engine/manifest.json +++ b/custom_components/shade_engine/manifest.json @@ -10,5 +10,5 @@ "issue_tracker": "https://github.com/vfilby/shade-engine/issues", "requirements": [], "single_config_entry": true, - "version": "0.5.0" + "version": "0.5.1" } diff --git a/custom_components/shade_engine/www/shade-engine-card.js b/custom_components/shade_engine/www/shade-engine-card.js index e1e3c7b..2125831 100644 --- a/custom_components/shade_engine/www/shade-engine-card.js +++ b/custom_components/shade_engine/www/shade-engine-card.js @@ -15,7 +15,7 @@ * the history strip, graph_hours (default 24) sets its window. */ -const CARD_VERSION = "0.5.0"; +const CARD_VERSION = "0.5.1"; const RAD = Math.PI / 180; const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v)); @@ -473,7 +473,24 @@ class ShadeEngineCard extends HTMLElement { } } -customElements.define("shade-engine-card", ShadeEngineCard); +/* Register the element only once Home Assistant's app has booted. + * + * The integration loads this module via `extra_module_url`, which the index + * page imports concurrently with app.js. Since HA 2026.8 the frontend installs + * the scoped-custom-element-registry polyfill, which REPLACES + * window.customElements with a fresh registry; anything defined on the native + * registry before that swap is invisible to customElements.get() and the + * dashboard shows "Custom element doesn't exist". With a warm cache this + * module reliably wins that race and loses the registry, so wait for HA's root + * element and then define on whatever registry is current. */ +function registerCard() { + const registry = window.customElements; + if (registry.get("shade-engine-card")) return; + registry.define("shade-engine-card", ShadeEngineCard); +} +customElements + .whenDefined("home-assistant") + .then(registerCard, registerCard); window.customCards = window.customCards || []; window.customCards.push({