diff --git a/custom_components/bahmcloud_store/panel/panel,js b/custom_components/bahmcloud_store/panel/panel,js
deleted file mode 100644
index 092e27b..0000000
--- a/custom_components/bahmcloud_store/panel/panel,js
+++ /dev/null
@@ -1,602 +0,0 @@
-class BahmcloudStorePanel extends HTMLElement {
- constructor() {
- super();
- this.attachShadow({ mode: "open" });
-
- this._hass = null;
-
- this._view = "store";
- this._data = null;
- this._loading = true;
- this._error = null;
-
- this._customAddUrl = "";
- this._customAddName = "";
-
- this._search = "";
- this._category = "all";
-
- this._detailRepoId = null;
- this._detailRepo = null;
-
- this._readmeLoading = false;
- this._readmeText = null;
- this._readmeHtml = null;
- this._readmeError = null;
- }
-
- set hass(hass) {
- this._hass = hass;
- if (!this._rendered) {
- this._rendered = true;
- this._render();
- this._load();
- }
- }
-
- async _load() {
- if (!this._hass) return;
-
- this._loading = true;
- this._error = null;
- this._update();
-
- try {
- const data = await this._hass.callApi("get", "bcs");
- this._data = data;
- } catch (e) {
- this._error = e?.message ? String(e.message) : String(e);
- } finally {
- this._loading = false;
- this._update();
- }
- }
-
- _isDesktop() {
- return window.matchMedia && window.matchMedia("(min-width: 1024px)").matches;
- }
-
- _toggleMenu() {
- if (this._isDesktop()) return;
- try {
- this.dispatchEvent(new Event("hass-toggle-menu", { bubbles: true, composed: true }));
- return;
- } catch (_) {}
- this._error = "Unable to open the sidebar on this client. Use the back button.";
- this._update();
- }
-
- _goBack() {
- if (this._view === "detail") {
- this._view = "store";
- this._detailRepoId = null;
- this._detailRepo = null;
- this._readmeText = null;
- this._readmeHtml = null;
- this._readmeError = null;
- this._update();
- return;
- }
- try {
- history.back();
- } catch (_) {
- window.location.href = "/";
- }
- }
-
- _openRepoDetail(repoId) {
- const repos = Array.isArray(this._data?.repos) ? this._data.repos : [];
- const repo = repos.find((r) => r.id === repoId);
- if (!repo) return;
-
- this._view = "detail";
- this._detailRepoId = repoId;
- this._detailRepo = repo;
-
- this._readmeText = null;
- this._readmeHtml = null;
- this._readmeError = null;
-
- this._update();
- this._loadReadme(repoId);
- }
-
- async _loadReadme(repoId) {
- if (!this._hass) return;
- this._readmeLoading = true;
- this._readmeError = null;
- this._update();
-
- try {
- const resp = await this._hass.callApi("get", `bcs/readme?repo_id=${encodeURIComponent(repoId)}`);
-
- if (resp?.ok && typeof resp.readme === "string" && resp.readme.trim()) {
- this._readmeText = resp.readme;
- this._readmeHtml = typeof resp.html === "string" && resp.html.trim() ? resp.html : null;
- } else {
- this._readmeText = null;
- this._readmeHtml = null;
- this._readmeError = resp?.message || "README not found.";
- }
- } catch (e) {
- this._readmeText = null;
- this._readmeHtml = null;
- this._readmeError = e?.message ? String(e.message) : String(e);
- } finally {
- this._readmeLoading = false;
- this._update();
- }
- }
-
- _render() {
- const root = this.shadowRoot;
-
- root.innerHTML = `
-
-
-
-
-
-
←
-
-
Bahmcloud Store
-
BCS — loading…
-
-
-
-
-
-
-
-
-
-
Store
-
Manage repositories
-
Settings / About
-
-
-
-
-
- `;
-
- root.getElementById("refreshBtn").addEventListener("click", () => this._load());
- root.getElementById("menuBtn").addEventListener("click", () => this._toggleMenu());
- root.getElementById("backBtn").addEventListener("click", () => this._goBack());
-
- for (const tab of root.querySelectorAll(".tab")) {
- tab.addEventListener("click", () => {
- this._view = tab.getAttribute("data-view");
- this._update();
- });
- }
-
- // Prevent HA global shortcuts while typing inside panel inputs
- const stopIfFormField = (e) => {
- const t = e.composedPath ? e.composedPath()[0] : e.target;
- if (!t) return;
- const tag = (t.tagName || "").toLowerCase();
- if (tag === "input" || tag === "textarea" || tag === "select" || t.isContentEditable) {
- e.stopPropagation();
- }
- };
- root.addEventListener("keydown", stopIfFormField, true);
- root.addEventListener("keyup", stopIfFormField, true);
- root.addEventListener("keypress", stopIfFormField, true);
- }
-
- _captureFocusState() {
- const root = this.shadowRoot;
- const ae = root.activeElement;
- if (!ae || !ae.id) return null;
-
- const supported = new Set(["searchInput", "categorySelect"]);
- if (!supported.has(ae.id)) return null;
-
- return {
- id: ae.id,
- value: ae.value,
- selectionStart: typeof ae.selectionStart === "number" ? ae.selectionStart : null,
- selectionEnd: typeof ae.selectionEnd === "number" ? ae.selectionEnd : null,
- };
- }
-
- _restoreFocusState(state) {
- if (!state) return;
- const root = this.shadowRoot;
- const el = root.getElementById(state.id);
- if (!el) return;
-
- try {
- el.focus({ preventScroll: true });
- if (state.selectionStart !== null && state.selectionEnd !== null && typeof el.setSelectionRange === "function") {
- el.setSelectionRange(state.selectionStart, state.selectionEnd);
- }
- } catch (_) {}
- }
-
- _update() {
- const root = this.shadowRoot;
- const focusState = this._captureFocusState();
-
- const content = root.getElementById("content");
- const err = root.getElementById("error");
- const subtitle = root.getElementById("subtitle");
-
- const v = this._data?.version ? String(this._data.version) : null;
- subtitle.textContent = v ? `BCS ${v}` : "BCS — loading…";
-
- for (const tab of root.querySelectorAll(".tab")) {
- tab.classList.toggle("active", tab.getAttribute("data-view") === this._view);
- }
-
- err.textContent = this._error ? `Error: ${this._error}` : "";
-
- if (this._loading) {
- content.innerHTML = `Loading…
`;
- this._restoreFocusState(focusState);
- return;
- }
-
- if (!this._data) {
- content.innerHTML = `No data.
`;
- this._restoreFocusState(focusState);
- return;
- }
-
- if (this._view === "store") {
- content.innerHTML = this._renderStore();
- this._wireStore();
- this._restoreFocusState(focusState);
- return;
- }
-
- if (this._view === "manage") {
- content.innerHTML = `Manage view is unchanged in this patch.
`;
- this._restoreFocusState(focusState);
- return;
- }
-
- if (this._view === "about") {
- content.innerHTML = this._renderAbout();
- this._restoreFocusState(focusState);
- return;
- }
-
- content.innerHTML = this._renderDetail();
- this._wireDetail();
- this._restoreFocusState(focusState);
- }
-
- _renderStore() {
- const repos = Array.isArray(this._data.repos) ? this._data.repos : [];
- const categories = Array.from(new Set(repos.map(r => (r.category || "").toLowerCase()).filter(Boolean))).sort();
-
- const filtered = repos
- .filter((r) => {
- const q = (this._search || "").trim().toLowerCase();
- if (!q) return true;
- const hay = `${r.name || ""} ${r.description || ""} ${r.url || ""} ${r.owner || ""}`.toLowerCase();
- return hay.includes(q);
- })
- .filter((r) => {
- if (this._category === "all") return true;
- return (r.category || "").toLowerCase() === this._category;
- });
-
- const options = [
- ``,
- ...categories.map((c) => ``),
- ].join("");
-
- const rows = filtered.map((r) => {
- const badge = r.source === "custom"
- ? `Custom`
- : `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 metaSrc = r.meta_source ? `Meta: ${r.meta_source}` : null;
-
- const lineBits = [creator, latest, metaSrc].filter(Boolean);
-
- return `
-
-
-
-
${this._esc(r.name)}
-
${this._esc(desc)}
-
${this._esc(lineBits.join(" · "))}
-
- ${badge}
-
-
- `;
- }).join("");
-
- return `
-
-
-
-
- ${rows || `No repositories configured.
`}
- `;
- }
-
- _wireStore() {
- const root = this.shadowRoot;
- const search = root.getElementById("searchInput");
- const cat = root.getElementById("categorySelect");
-
- if (search) {
- search.addEventListener("input", (e) => {
- this._search = e.target.value;
- this._update();
- });
- }
-
- if (cat) {
- cat.addEventListener("change", (e) => {
- this._category = String(e.target.value || "all");
- this._update();
- });
- }
-
- for (const card of root.querySelectorAll("[data-repo]")) {
- card.addEventListener("click", () => {
- const id = card.getAttribute("data-repo");
- if (id) this._openRepoDetail(id);
- });
- }
- }
-
- _renderDetail() {
- const r = this._detailRepo;
- if (!r) return `Repository not found.
`;
-
- const badge = r.source === "custom"
- ? `Custom`
- : `Index`;
-
- const desc = r.description || "No description available.";
- const latest = r.latest_version ? `Latest: ${r.latest_version}` : "Latest: unknown";
-
- const infoBits = [
- r.owner ? `Creator: ${r.owner}` : "Creator: -",
- latest,
- r.provider ? `Provider: ${r.provider}` : null,
- r.meta_source ? `Meta: ${r.meta_source}` : null,
- ].filter(Boolean);
-
- const readmeBlock = this._readmeLoading
- ? `Loading README…
`
- : this._readmeText
- ? `
-
-
README
-
-
-
- Show raw Markdown
-
-
${this._esc(this._readmeText)}
-
-
-
- `
- : `
-
-
README
-
${this._esc(this._readmeError || "README not found.")}
-
- `;
-
- return `
-
-
-
-
-
-
${this._esc(r.name)}
-
${this._esc(desc)}
-
${this._esc(infoBits.join(" · "))}
-
-
- ${badge}
-
-
-
- ${readmeBlock}
-
-
-
-
-
Installation & Updates
-
Buttons will be enabled in a later version.
-
-
-
- `;
- }
-
- _wireDetail() {
- const root = this.shadowRoot;
- const pretty = root.getElementById("readmePretty");
- if (!pretty) return;
-
- if (this._readmeHtml) {
- pretty.innerHTML = this._readmeHtml;
- } else if (this._readmeText) {
- // If backend could not render HTML, show a friendly fallback text
- pretty.innerHTML = `Markdown rendering is not available. Please use "Show raw Markdown".
`;
- }
- }
-
- _renderAbout() {
- return `
-
-
Settings / About
-
BCS version: ${this._esc(this._data.version || "-")}
-
- `;
- }
-
- _esc(s) {
- return String(s ?? "")
- .replaceAll("&", "&")
- .replaceAll("<", "<")
- .replaceAll(">", ">")
- .replaceAll('"', """)
- .replaceAll("'", "'");
- }
-}
-
-customElements.define("bahmcloud-store-panel", BahmcloudStorePanel);