diff --git a/custom_components/bahmcloud_store/panel/panel.js b/custom_components/bahmcloud_store/panel/panel.js
index 98b500e..3b39102 100644
--- a/custom_components/bahmcloud_store/panel/panel.js
+++ b/custom_components/bahmcloud_store/panel/panel.js
@@ -21,6 +21,9 @@ class BahmcloudStorePanel extends HTMLElement {
this._readmeLoading = false;
this._readmeText = null;
this._readmeError = null;
+
+ // Prevent multiple concurrent markdown mounts
+ this._mdMountToken = 0;
}
set hass(hass) {
@@ -335,6 +338,11 @@ class BahmcloudStorePanel extends HTMLElement {
details{ margin-top: 10px; }
summary{ cursor:pointer; color: var(--bcs-accent); font-weight: 800; }
+
+ /* Make HA markdown look nice inside our card */
+ ha-markdown{
+ display:block;
+ }
@@ -388,9 +396,7 @@ class BahmcloudStorePanel extends HTMLElement {
tag === "select" ||
t.isContentEditable;
- if (isEditable) {
- e.stopPropagation();
- }
+ if (isEditable) e.stopPropagation();
};
root.addEventListener("keydown", stopIfFormField, true);
@@ -406,13 +412,12 @@ class BahmcloudStorePanel extends HTMLElement {
const supported = new Set(["searchInput", "categorySelect", "addUrl", "addName"]);
if (!supported.has(ae.id)) return null;
- const state = {
+ return {
id: ae.id,
value: ae.value,
selectionStart: typeof ae.selectionStart === "number" ? ae.selectionStart : null,
selectionEnd: typeof ae.selectionEnd === "number" ? ae.selectionEnd : null,
};
- return state;
}
_restoreFocusState(state) {
@@ -431,7 +436,6 @@ class BahmcloudStorePanel extends HTMLElement {
_update() {
const root = this.shadowRoot;
-
const focusState = this._captureFocusState();
const content = root.getElementById("content");
@@ -515,13 +519,11 @@ class BahmcloudStorePanel extends HTMLElement {
: `Index`;
const desc = r.description || "No description available.";
-
const creator = r.owner ? `Creator: ${r.owner}` : "Creator: -";
+ const latest = r.latest_version ? `Latest: ${r.latest_version}` : "Latest: unknown";
const cat = r.category ? `Category: ${r.category}` : null;
const metaSrc = r.meta_source ? `Meta: ${r.meta_source}` : null;
- const latest = r.latest_version ? `Latest: ${r.latest_version}` : "Latest: unknown";
-
const lineBits = [creator, latest, cat, metaSrc].filter(Boolean);
return `
@@ -552,7 +554,6 @@ class BahmcloudStorePanel extends HTMLElement {
_wireStore() {
const root = this.shadowRoot;
-
const search = root.getElementById("searchInput");
const cat = root.getElementById("categorySelect");
@@ -587,7 +588,6 @@ class BahmcloudStorePanel extends HTMLElement {
: `Index`;
const desc = r.description || "No description available.";
-
const latest = r.latest_version ? `Latest: ${r.latest_version}` : "Latest: unknown";
const infoBits = [
@@ -659,6 +659,60 @@ class BahmcloudStorePanel extends HTMLElement {
`;
}
+ async _mountPrettyMarkdown(container, markdown) {
+ // token prevents race conditions when switching repos fast
+ const token = ++this._mdMountToken;
+
+ container.innerHTML = "";
+
+ // If user switched views/repo while we were waiting
+ const stillValid = () => token === this._mdMountToken && this._view === "detail" && !!this._readmeText;
+
+ // Wait until HA registers the component
+ try {
+ await customElements.whenDefined("ha-markdown");
+ } catch (_) {
+ // ignored
+ }
+ if (!stillValid()) return;
+
+ // Create markdown element
+ let el;
+ try {
+ el = document.createElement("ha-markdown");
+ } catch (_) {
+ el = null;
+ }
+
+ // If creation failed, fallback to plain pre
+ if (!el) {
+ const pre = document.createElement("pre");
+ pre.className = "readme";
+ pre.textContent = markdown;
+ container.appendChild(pre);
+ return;
+ }
+
+ // Attach first (some HA internals react after connection)
+ container.appendChild(el);
+
+ // Set hass + content
+ try { el.hass = this._hass; } catch (_) {}
+ try { el.content = markdown; } catch (_) {
+ // some builds used `markdown` property in the past
+ try { el.markdown = markdown; } catch (_) {}
+ }
+
+ // Nudge render (some builds need a microtask/frame after setting properties)
+ await new Promise((resolve) => requestAnimationFrame(resolve));
+ if (!stillValid()) return;
+
+ try { el.hass = this._hass; } catch (_) {}
+ try { el.content = markdown; } catch (_) {
+ try { el.markdown = markdown; } catch (_) {}
+ }
+ }
+
_wireDetail() {
const root = this.shadowRoot;
const container = root.getElementById("readmeContainer");
@@ -668,26 +722,8 @@ class BahmcloudStorePanel extends HTMLElement {
if (!this._readmeText) return;
- // Only attempt ha-markdown if the custom element exists
- const hasHaMarkdown = typeof customElements !== "undefined" && !!customElements.get("ha-markdown");
-
- if (hasHaMarkdown) {
- try {
- const el = document.createElement("ha-markdown");
- try { el.hass = this._hass; } catch (_) {}
- el.content = this._readmeText;
- container.appendChild(el);
- return;
- } catch (_) {
- // fall through to raw fallback (details already exists)
- }
- }
-
- // If ha-markdown is missing, show a minimal rendered area:
- const pre = document.createElement("pre");
- pre.className = "readme";
- pre.textContent = this._readmeText;
- container.appendChild(pre);
+ // Always try pretty markdown; raw fallback is already available in
+ this._mountPrettyMarkdown(container, this._readmeText);
}
_renderFabs() {