This commit is contained in:
Home Assistant Version Control committed 2026-09-02 17:25:42 +00:00
1 parent ce1a5a5fe9
commit 96984f8a7c
20 files changed
+417 -284

No files matched your search

+1 -1
View File
@@ -51,7 +51,7 @@
}, },
{ {
"id": "6ad5d0d7a4c9435a85476e49d22d4df4", "id": "6ad5d0d7a4c9435a85476e49d22d4df4",
"url": "/hacsfiles/versatile-thermostat-ui-card/versatile-thermostat-ui-card.js?hacstag=714354847320", "url": "/hacsfiles/versatile-thermostat-ui-card/versatile-thermostat-ui-card.js?hacstag=714354847330",
"type": "module" "type": "module"
}, },
{ {
+1 -1
View File
@@ -25,7 +25,7 @@ DOMAIN = "ha_mcp_tools"
# in CI. The # in CI. The
# capability negotiation — not this version — gates each WS command (see # capability negotiation — not this version — gates each WS command (see
# ``websocket_api.CAPABILITIES``). # ``websocket_api.CAPABILITIES``).
COMPONENT_VERSION = "2.1.0" COMPONENT_VERSION = "2.1.1"
# Config-entry discriminator (``entry.data[CONF_ENTRY_TYPE]``). A missing value # Config-entry discriminator (``entry.data[CONF_ENTRY_TYPE]``). A missing value
# means "tools" so the pre-existing services entry keeps working across the # means "tools" so the pre-existing services entry keeps working across the
+1 -1
View File
@@ -22,5 +22,5 @@
"requirements": [ "requirements": [
"ruamel.yaml>=0.18.0" "ruamel.yaml>=0.18.0"
], ],
"version": "2.1.0" "version": "2.1.1"
} }
+35 -50
View File
@@ -29,7 +29,7 @@ mapping); the ``ha_auth`` bearer check + discovery documents mirror the add-on's
``auth_native.py`` + the ``ha_auth`` subset of ``oauth.py``; the ``legacy`` ``auth_native.py`` + the ``ha_auth`` subset of ``oauth.py``; the ``legacy``
provider + its root ``/authorize`` + ``/token`` views live in provider + its root ``/authorize`` + ``/token`` views live in
:mod:`oauth_legacy`, ported from the ``legacy`` subset of the add-on's :mod:`oauth_legacy`, ported from the ``legacy`` subset of the add-on's
``oauth.py``. The seven RFC 8414 / RFC 9728 discovery views below are shared by ``oauth.py``. The six RFC 8414 / RFC 9728 discovery views below are shared by
``ha_auth``, ``legacy``, and ``none`` (which serves a distinct auto-approve ``ha_auth``, ``legacy``, and ``none`` (which serves a distinct auto-approve
authorization-server document pointing at :mod:`oauth_autoapprove`'s endpoints) authorization-server document pointing at :mod:`oauth_autoapprove`'s endpoints)
— see :func:`active_auth_mode`. — see :func:`active_auth_mode`.
@@ -387,39 +387,6 @@ def _none_mode_authorization_server_document(base: str) -> dict[str, Any]:
} }
class _ProtectedResourceMetadataView(HomeAssistantView):
"""RFC 9728 Protected Resource Metadata."""
requires_auth = False
cors_allowed = True
url = f"{OAUTH_BASE}/protected-resource"
name = "ha_mcp_tools:oauth:protected-resource"
def __init__(self, hass: HomeAssistant) -> None:
"""Bind the view to the HA instance; liveness is resolved per request."""
self._hass = hass
async def get(self, request: web.Request) -> web.Response:
"""Serve the protected-resource document for the bearer-gated modes only.
SECURITY (#1976 review): this ANONYMOUS, fixed (guessable) path exposes
``resource: <base>/api/webhook/<id>``. In none mode the webhook id is the
SOLE credential, so serving it here would leak it to any unauthenticated
GET. Serve only for ``ha_auth``/``legacy`` (where the id is not a secret
and the 401 ``WWW-Authenticate`` pointer legitimately directs a client
here); 404 otherwise. The PATH-SCOPED well-known view still serves in none
mode — its caller must already know the id (it is a route parameter).
"""
if active_auth_mode(self._hass) not in (WEBHOOK_AUTH_HA, WEBHOOK_AUTH_LEGACY):
return _json_not_found()
webhook_id = _active_webhook_id(self._hass)
if webhook_id is None:
return _json_not_found()
return web.json_response(
_protected_resource_document(webhook_id, _build_base_url(request))
)
class _AuthorizationServerMetadataView(HomeAssistantView): class _AuthorizationServerMetadataView(HomeAssistantView):
"""RFC 8414 Authorization Server Metadata. """RFC 8414 Authorization Server Metadata.
@@ -450,12 +417,23 @@ class _AuthorizationServerMetadataView(HomeAssistantView):
class _WellKnownProtectedResourceView(HomeAssistantView): class _WellKnownProtectedResourceView(HomeAssistantView):
"""RFC 9728 §3.1 path-scoped Protected Resource Metadata. """RFC 9728 §3.1 path-scoped Protected Resource Metadata — the ONLY
protected-resource document this integration serves.
Same document as :class:`_ProtectedResourceMetadataView`, served at the Served at the well-known location derived from the webhook resource URL
well-known location derived from the webhook resource URL — claude.ai's (``/.well-known/oauth-protected-resource/api/webhook/<id>``), which is also
first fallback probe when the 401's ``resource_metadata`` pointer is where the webhook's 401 ``resource_metadata`` challenge points, and which is
missing. The webhook id is a ROUTE PARAMETER (not baked into the path at claude.ai's first fallback probe when that pointer is missing.
SECURITY (#1976 review): there is deliberately NO fixed-path variant of this
document. A fixed, guessable path handed ``resource: <base>/api/webhook/<id>``
to any anonymous GET while ``ha_auth``/``legacy`` was on, and a later switch
back to ``none`` mode — where the webhook id is the SOLE credential —
promoted that already-published value into the credential. This view's
caller must already hold the id (it is a route parameter), so the document
discloses nothing in any mode.
The webhook id is a ROUTE PARAMETER (not baked into the path at
registration): a remove + re-add of the entry mints a new webhook id in the registration): a remove + re-add of the entry mints a new webhook id in the
same HA session, and the bound view must serve whichever id is currently same HA session, and the bound view must serve whichever id is currently
live (404 for any other). Standalone view (not a subclass of the plain live (404 for any other). Standalone view (not a subclass of the plain
@@ -496,10 +474,11 @@ class _WellKnownAuthorizationServerMetadataView(_AuthorizationServerMetadataView
def _metadata_views(hass: HomeAssistant) -> list[HomeAssistantView]: def _metadata_views(hass: HomeAssistant) -> list[HomeAssistantView]:
"""Build the seven discovery-document views, shared by ha_auth and legacy """Build the six discovery-document views, shared by ha_auth and legacy
(mode-agnostic — each view resolves the active mode per request).""" (mode-agnostic — each view resolves the active mode per request): the
path-scoped protected-resource document, the authorization-server document,
and the four RFC 8414 / OIDC well-known authorization-server locations."""
views: list[HomeAssistantView] = [ views: list[HomeAssistantView] = [
_ProtectedResourceMetadataView(hass),
_AuthorizationServerMetadataView(hass), _AuthorizationServerMetadataView(hass),
_WellKnownProtectedResourceView(hass), _WellKnownProtectedResourceView(hass),
] ]
@@ -528,7 +507,7 @@ def _metadata_views(hass: HomeAssistant) -> list[HomeAssistantView]:
def _register_metadata_views(hass: HomeAssistant) -> None: def _register_metadata_views(hass: HomeAssistant) -> None:
"""Register the seven discovery views at most once per HA session. """Register the six discovery views at most once per HA session.
aiohttp cannot unregister a bound view, so a reload / re-enable / re-add / aiohttp cannot unregister a bound view, so a reload / re-enable / re-add /
ha_auth<->legacy mode switch must all reuse the already-bound views — they ha_auth<->legacy mode switch must all reuse the already-bound views — they
@@ -551,15 +530,21 @@ def _register_metadata_views(hass: HomeAssistant) -> None:
hass.data[_OAUTH_VIEWS_REGISTERED_KEY] = True hass.data[_OAUTH_VIEWS_REGISTERED_KEY] = True
def _build_unauthorized_response(request: web.Request) -> web.Response: def _build_unauthorized_response(request: web.Request, webhook_id: str) -> web.Response:
"""Build the 401 + ``WWW-Authenticate`` challenge MCP clients use to discover. """Build the 401 + ``WWW-Authenticate`` challenge MCP clients use to discover.
Per RFC 9728 §5.1 / MCP spec, the ``resource_metadata`` parameter points to Per RFC 9728 §5.1 / MCP 2026-07-28 Authorization Server Discovery, the
the protected-resource metadata URL where the client finds the authorization ``resource_metadata`` parameter points to the protected-resource metadata
server. URL where the client finds the authorization server.
""" """
base = _build_base_url(request) base = _build_base_url(request)
metadata_url = f"{base}{OAUTH_BASE}/protected-resource" # RFC 9728 §3.1 path-scoped location. The pointer names the id, but this
# 401 is only produced on a request TO /api/webhook/<id>, so the caller
# already holds it; there is no fixed-path document to point at (see
# _WellKnownProtectedResourceView).
metadata_url = (
f"{base}/.well-known/oauth-protected-resource/api/webhook/{webhook_id}"
)
return web.Response( return web.Response(
status=401, status=401,
text="Unauthorized", text="Unauthorized",
@@ -592,10 +577,10 @@ async def _check_webhook_auth(
if resource_server is not None and not await resource_server.validate_request( if resource_server is not None and not await resource_server.validate_request(
request request
): ):
return _build_unauthorized_response(request) return _build_unauthorized_response(request, cfg["webhook_id"])
oauth_provider: LegacyOAuthProvider | None = cfg.get("oauth_provider") oauth_provider: LegacyOAuthProvider | None = cfg.get("oauth_provider")
if oauth_provider is not None and not oauth_provider.validate_bearer(request): if oauth_provider is not None and not oauth_provider.validate_bearer(request):
return _build_unauthorized_response(request) return _build_unauthorized_response(request, cfg["webhook_id"])
return None return None
@@ -49,7 +49,7 @@ from __future__ import annotations
import logging import logging
import secrets import secrets
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
from urllib.parse import urlparse from urllib.parse import urlencode, urlparse
import aiohttp import aiohttp
from aiohttp import web from aiohttp import web
@@ -303,13 +303,23 @@ class AutoApproveAuthorizeView(HomeAssistantView):
if forward_id != client_id: if forward_id != client_id:
params.popall("client_id", None) params.popall("client_id", None)
params["client_id"] = forward_id params["client_id"] = forward_id
import yarl
# Keep the browser hop relative, matching the token leg. Browsers cannot # Keep the browser hop relative, matching the token leg. Browsers cannot
# be made to send X-Forwarded-Host, so this is consistency rather than a # be made to send X-Forwarded-Host, so this is consistency rather than a
# vulnerability fix. # vulnerability fix.
target = yarl.URL("/auth/authorize").with_query(params)
return web.Response(status=302, headers={"Location": str(target)}) # Percent-encode the query instead of handing the params to yarl: yarl
# legally leaves ":" and "/" literal inside query values (RFC 3986
# permits both in the query component), so a loopback client's callback
# forwards as ``redirect_uri=http://127.0.0.1:1234/callback``. Reverse
# proxies shipping a generic "block common exploits" ruleset -- Nginx
# Proxy Manager enables one per host with a checkbox -- match
# ``[a-zA-Z0-9_]=http://`` and answer 403 before core ever sees the
# request, stranding every native-app client behind such a proxy.
# Full encoding is semantically identical and survives those filters.
query = urlencode(list(params.items()))
target = f"/auth/authorize?{query}" if query else "/auth/authorize"
return web.Response(status=302, headers={"Location": target})
async def post(self, request: web.Request) -> web.Response: async def post(self, request: web.Request) -> web.Response:
"""Handle a legacy-mode consent submission on the scoped route.""" """Handle a legacy-mode consent submission on the scoped route."""
@@ -29,11 +29,11 @@
"title": "Nástroje souborů a YAML HA-MCP", "title": "Nástroje souborů a YAML HA-MCP",
"description": "Nakonfigurujte privilegované služby pro úpravu souborů a YAML používané volitelnými nástroji souborů/YAML ha-mcp. Tato nastavení se také zobrazují v uživatelském rozhraní nastavení serveru ha-mcp a aplikují se okamžitě, bez restartu. Nepřepisovatelná úroveň zákazu stále blokuje citlivé cesty (např. .storage) a klíče hranice důvěry (homeassistant, http, frontend, lovelace).", "description": "Nakonfigurujte privilegované služby pro úpravu souborů a YAML používané volitelnými nástroji souborů/YAML ha-mcp. Tato nastavení se také zobrazují v uživatelském rozhraní nastavení serveru ha-mcp a aplikují se okamžitě, bez restartu. Nepřepisovatelná úroveň zákazu stále blokuje citlivé cesty (např. .storage) a klíče hranice důvěry (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Další adresáře souborů", "allowed_dirs": "Další cesta k souborům",
"extra_yaml_keys": "Další klíče pro zápis YAML" "extra_yaml_keys": "Další klíče pro zápis YAML"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Adresáře vzhledem ke konfiguračnímu adresáři, každému je uděleno právo čtení a zápisu (např. pyscript). Průchod a položky mimo konfiguraci jsou zahozeny.", "allowed_dirs": "Cesty relativní k adresáři konfigurace, včetně přesných názvů souborů, jako je sensor.yaml, nebo cesty pod /share, /media, /ssl a /backup. Každá položka má uděleno oprávnění pro čtení a zápis pro danou cestu a vše pod ní; každou cestu zadejte jako samostatnou položku seznamu. Adresářový posun (traversal) a jiné nepovolené cesty budou ignorovány.",
"extra_yaml_keys": "Klíče nejvyšší úrovně, které ha_config_set_yaml může zapisovat navíc k vestavěným, pro integrace s prioritou YAML v této instalaci (např. alert2). Klíče hranice důvěry jsou zahozeny." "extra_yaml_keys": "Klíče nejvyšší úrovně, které ha_config_set_yaml může zapisovat navíc k vestavěným, pro integrace s prioritou YAML v této instalaci (např. alert2). Klíče hranice důvěry jsou zahozeny."
} }
}, },
@@ -29,11 +29,11 @@
"title": "HA-MCP File & YAML Tools", "title": "HA-MCP File & YAML Tools",
"description": "Konfiguriere die privilegierten Datei- und YAML-Bearbeitungsdienste, die von den opt-in Datei/YAML-Tools von ha-mcp verwendet werden. Diese Einstellungen erscheinen auch in der eigenen Einstellungs-UI des ha-mcp-Servers und werden live wirksam, ohne Neustart. Eine nicht überschreibbare Deny-Grenze blockiert weiterhin sensible Pfade (z. B. .storage) und Vertrauensgrenzen-Keys (homeassistant, http, frontend, lovelace).", "description": "Konfiguriere die privilegierten Datei- und YAML-Bearbeitungsdienste, die von den opt-in Datei/YAML-Tools von ha-mcp verwendet werden. Diese Einstellungen erscheinen auch in der eigenen Einstellungs-UI des ha-mcp-Servers und werden live wirksam, ohne Neustart. Eine nicht überschreibbare Deny-Grenze blockiert weiterhin sensible Pfade (z. B. .storage) und Vertrauensgrenzen-Keys (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Zusätzliche Datei-Verzeichnisse", "allowed_dirs": "Zusätzliche Dateipfade",
"extra_yaml_keys": "Zusätzliche YAML-Schreib-Keys" "extra_yaml_keys": "Zusätzliche YAML-Schreib-Keys"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Verzeichnisse relativ zum Konfigurationsverzeichnis, jeweils mit Lese- und Schreibzugriff (z. B. pyscript). Traversal- und Einträge außerhalb des Konfig-Verzeichnisses werden verworfen.", "allowed_dirs": "Pfade relativ zum Konfigurationsverzeichnis, einschließlich genauer Dateinamen wie sensor.yaml, oder Pfade unter /share, /media, /ssl und /backup. Jedem Eintrag wird Lese- und Schreibzugriff für diesen Pfad und alles darunter gewährt; gib jeden Pfad als separaten Listeneintrag an. Verzeichnistraversierung und andere nicht erlaubte Pfade werden verworfen.",
"extra_yaml_keys": "Top-Level-Keys, die ha_config_set_yaml zusätzlich zu den eingebauten schreiben darf, für YAML-first-Integrationen auf dieser Installation (z. B. alert2). Vertrauensgrenzen-Keys werden verworfen." "extra_yaml_keys": "Top-Level-Keys, die ha_config_set_yaml zusätzlich zu den eingebauten schreiben darf, für YAML-first-Integrationen auf dieser Installation (z. B. alert2). Vertrauensgrenzen-Keys werden verworfen."
} }
}, },
@@ -29,11 +29,11 @@
"title": "HA-MCP Dosieraj & YAML Iloj", "title": "HA-MCP Dosieraj & YAML Iloj",
"description": "Agordu la privilegiajn dosierajn kaj YAML-redaktajn servojn uzatajn de la laŭvolaj dosieraj/YAML-iloj de ha-mcp. Ĉi tiuj agordoj ankaŭ aperas en la propra agorda UI de la ha-mcp servilo kaj aplikiĝas tuj, sen rekomenco. Ne-superregebla malpermesa limo ankoraŭ blokas sentemajn vojojn (ekz. .storage) kaj fid-limajn ŝlosilojn (homeassistant, http, frontend, lovelace).", "description": "Agordu la privilegiajn dosierajn kaj YAML-redaktajn servojn uzatajn de la laŭvolaj dosieraj/YAML-iloj de ha-mcp. Ĉi tiuj agordoj ankaŭ aperas en la propra agorda UI de la ha-mcp servilo kaj aplikiĝas tuj, sen rekomenco. Ne-superregebla malpermesa limo ankoraŭ blokas sentemajn vojojn (ekz. .storage) kaj fid-limajn ŝlosilojn (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Ekstraj dosierujoj", "allowed_dirs": "Kromaj dosiervojoj",
"extra_yaml_keys": "Ekstraj YAML-skribaj ŝlosiloj" "extra_yaml_keys": "Ekstraj YAML-skribaj ŝlosiloj"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Dosierujoj rilataj al la agorda dosierujo, ĉiu kun legado kaj skribado permesita (ekz. pyscript). Trairo kaj ekster-agordaj eniroj estas forĵetitaj.", "allowed_dirs": "Vojoj relative al la agorda dosierujo, inkluzive de ekzakta dosiernomo kiel sensor.yaml, aŭ vojoj sub /share, /media, /ssl, kaj /backup. Ĉiu eniro ricevas leg- kaj skrib-permeson por tiu vojo kaj ĉio sub ĝi; enigu ĉiun vojon kiel apartan listan eron. Trairado kaj aliaj nepermesitaj vojoj estas forigitaj.",
"extra_yaml_keys": "Ĉefnivelaj ŝlosiloj, kiujn ha_config_set_yaml povas skribi krom la enkonstruitaj, por YAML-unuaj integriĝoj en ĉi tiu instalaĵo (ekz. alert2). Fid-limaj ŝlosiloj estas forĵetitaj." "extra_yaml_keys": "Ĉefnivelaj ŝlosiloj, kiujn ha_config_set_yaml povas skribi krom la enkonstruitaj, por YAML-unuaj integriĝoj en ĉi tiu instalaĵo (ekz. alert2). Fid-limaj ŝlosiloj estas forĵetitaj."
} }
}, },
@@ -29,11 +29,11 @@
"title": "Herramientas de archivos y YAML de HA-MCP", "title": "Herramientas de archivos y YAML de HA-MCP",
"description": "Configura los servicios privilegiados de edición de archivos y YAML que usan las herramientas opcionales de archivos/YAML de ha-mcp. Estos ajustes aparecen también en la propia interfaz de ajustes del servidor ha-mcp y se aplican en caliente, sin reiniciar. Un mínimo de denegación no anulable sigue bloqueando rutas sensibles (p. ej. .storage) y claves de la frontera de confianza (homeassistant, http, frontend, lovelace).", "description": "Configura los servicios privilegiados de edición de archivos y YAML que usan las herramientas opcionales de archivos/YAML de ha-mcp. Estos ajustes aparecen también en la propia interfaz de ajustes del servidor ha-mcp y se aplican en caliente, sin reiniciar. Un mínimo de denegación no anulable sigue bloqueando rutas sensibles (p. ej. .storage) y claves de la frontera de confianza (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Directorios de archivos adicionales", "allowed_dirs": "Rutas de archivos adicionales",
"extra_yaml_keys": "Claves YAML de escritura adicionales" "extra_yaml_keys": "Claves YAML de escritura adicionales"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Directorios relativos al directorio de configuración, cada uno con permiso de lectura y escritura (p. ej. pyscript). Se descartan los recorridos de ruta y las entradas fuera de la configuración.", "allowed_dirs": "Rutas relativas al directorio de configuración, incluidos nombres de archivo exactos como sensor.yaml, o rutas bajo /share, /media, /ssl y /backup. A cada entrada se le concede lectura y escritura para esa ruta y todo lo que esté debajo de ella; introduce cada ruta como un elemento de lista separado. Se descartarán los recorridos de directorios y otras rutas no permitidas.",
"extra_yaml_keys": "Claves de primer nivel que ha_config_set_yaml puede escribir además de las integradas, para integraciones basadas en YAML de esta instalación (p. ej. alert2). Las claves de la frontera de confianza se descartan." "extra_yaml_keys": "Claves de primer nivel que ha_config_set_yaml puede escribir además de las integradas, para integraciones basadas en YAML de esta instalación (p. ej. alert2). Las claves de la frontera de confianza se descartan."
} }
}, },
@@ -29,11 +29,11 @@
"title": "Outils Fichier & YAML HA-MCP", "title": "Outils Fichier & YAML HA-MCP",
"description": "Configurez les services privilégiés d'édition de fichiers et de YAML utilisés par les outils fichier/YAML optionnels de ha-mcp. Ces paramètres apparaissent également dans l'interface de configuration du serveur ha-mcp et s'appliquent en direct, sans redémarrage. Un plancher de refus non contournable bloque toujours les chemins sensibles (ex. .storage) et les clés de limite de confiance (homeassistant, http, frontend, lovelace).", "description": "Configurez les services privilégiés d'édition de fichiers et de YAML utilisés par les outils fichier/YAML optionnels de ha-mcp. Ces paramètres apparaissent également dans l'interface de configuration du serveur ha-mcp et s'appliquent en direct, sans redémarrage. Un plancher de refus non contournable bloque toujours les chemins sensibles (ex. .storage) et les clés de limite de confiance (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Répertoires de fichiers supplémentaires", "allowed_dirs": "Chemins de fichiers supplémentaires",
"extra_yaml_keys": "Clés d'écriture YAML supplémentaires" "extra_yaml_keys": "Clés d'écriture YAML supplémentaires"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Répertoires relatifs au répertoire de configuration, chacun avec accès en lecture et écriture (ex. pyscript). Les traversées et les entrées hors du répertoire de configuration sont ignorées.", "allowed_dirs": "Chemins relatifs au répertoire de configuration, incluant les noms de fichiers exacts tels que sensor.yaml, ou les chemins sous /share, /media, /ssl et /backup. Chaque entrée bénéficie d'un accès en lecture et en écriture pour ce chemin et tout ce qu'il contient ; saisissez chaque chemin comme un élément de liste séparé. Les parcours de répertoires (traversal) et autres chemins non autorisés sont ignorés.",
"extra_yaml_keys": "Clés de premier niveau que ha_config_set_yaml peut écrire en plus de celles intégrées, pour les intégrations YAML-first de cette installation (ex. alert2). Les clés de limite de confiance sont ignorées." "extra_yaml_keys": "Clés de premier niveau que ha_config_set_yaml peut écrire en plus de celles intégrées, pour les intégrations YAML-first de cette installation (ex. alert2). Les clés de limite de confiance sont ignorées."
} }
}, },
@@ -29,11 +29,11 @@
"title": "Strumenti file e YAML di HA-MCP", "title": "Strumenti file e YAML di HA-MCP",
"description": "Configura i servizi privilegiati di modifica di file e YAML usati dagli strumenti file/YAML opzionali di ha-mcp. Queste impostazioni compaiono anche nell'interfaccia delle impostazioni del server ha-mcp e si applicano subito, senza riavvio. Una soglia di divieto non aggirabile continua a bloccare i percorsi sensibili (per esempio .storage) e le chiavi del confine di fiducia (homeassistant, http, frontend, lovelace).", "description": "Configura i servizi privilegiati di modifica di file e YAML usati dagli strumenti file/YAML opzionali di ha-mcp. Queste impostazioni compaiono anche nell'interfaccia delle impostazioni del server ha-mcp e si applicano subito, senza riavvio. Una soglia di divieto non aggirabile continua a bloccare i percorsi sensibili (per esempio .storage) e le chiavi del confine di fiducia (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Directory di file aggiuntive", "allowed_dirs": "Percorsi file extra",
"extra_yaml_keys": "Chiavi YAML scrivibili aggiuntive" "extra_yaml_keys": "Chiavi YAML scrivibili aggiuntive"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Directory relative alla directory di configurazione, ciascuna con permesso di lettura e scrittura (per esempio pyscript). I percorsi che risalgono l'albero e le voci fuori dalla configurazione vengono scartati.", "allowed_dirs": "Percorsi relativi alla directory di configurazione, inclusi nomi di file esatti come sensor.yaml, o percorsi sotto /share, /media, /ssl e /backup. A ciascuna voce viene concesso l'accesso in lettura e scrittura per quel percorso e per tutto ciò che si trova al di sotto; inserisci ogni percorso come elemento di elenco separato. I percorsi di attraversamento e altri non consentiti vengono scartati.",
"extra_yaml_keys": "Chiavi di primo livello che ha_config_set_yaml può scrivere oltre a quelle integrate, per le integrazioni basate su YAML di questa installazione (per esempio alert2). Le chiavi del confine di fiducia vengono scartate." "extra_yaml_keys": "Chiavi di primo livello che ha_config_set_yaml può scrivere oltre a quelle integrate, per le integrazioni basate su YAML di questa installazione (per esempio alert2). Le chiavi del confine di fiducia vengono scartate."
} }
}, },
@@ -29,11 +29,11 @@
"title": "HA-MCP 파일 및 YAML 도구", "title": "HA-MCP 파일 및 YAML 도구",
"description": "ha-mcp의 선택형 파일/YAML 도구가 사용하는, 권한이 필요한 파일 및 YAML 편집 서비스를 구성합니다. 이 설정은 ha-mcp 서버 자체의 설정 UI에도 나타나며 다시 시작하지 않아도 즉시 적용됩니다. 재정의할 수 없는 기본 차단 규칙은 민감한 경로(예: .storage)와 신뢰 경계 키(homeassistant, http, frontend, lovelace)를 계속 차단합니다.", "description": "ha-mcp의 선택형 파일/YAML 도구가 사용하는, 권한이 필요한 파일 및 YAML 편집 서비스를 구성합니다. 이 설정은 ha-mcp 서버 자체의 설정 UI에도 나타나며 다시 시작하지 않아도 즉시 적용됩니다. 재정의할 수 없는 기본 차단 규칙은 민감한 경로(예: .storage)와 신뢰 경계 키(homeassistant, http, frontend, lovelace)를 계속 차단합니다.",
"data": { "data": {
"allowed_dirs": "추가 파일 디렉터리", "allowed_dirs": "추가 파일 경로",
"extra_yaml_keys": "추가 YAML 쓰기 허용 키" "extra_yaml_keys": "추가 YAML 쓰기 허용 키"
}, },
"data_description": { "data_description": {
"allowed_dirs": "설정 디렉터리 기준 상대 디렉터리이며 각각 읽기와 쓰기가 허용됩니다(예: pyscript). 경로 탈출과 설정 디렉터리 밖의 항목은 무시됩니다.", "allowed_dirs": "sensor.yaml 같은 정확한 파일 이름을 포함하여 config 디렉토리 상대 경로, 또는 /share, /media, /ssl, /backup 아래의 경로입니다. 각 항목에는 해당 경로 및 그 하위 경로에 대한 읽기 및 쓰기 권한이 부여되며, 각 경로는 별도의 목록 항목으로 입력하세요. 상위 디렉토리 순회 및 허용되지 않는 경로는 제외됩니다.",
"extra_yaml_keys": "이 설치본에서 YAML 우선으로 동작하는 통합 구성요소(예: alert2)를 위해, ha_config_set_yaml이 기본 허용 키 외에 추가로 쓸 수 있는 최상위 키입니다. 신뢰 경계 키는 무시됩니다." "extra_yaml_keys": "이 설치본에서 YAML 우선으로 동작하는 통합 구성요소(예: alert2)를 위해, ha_config_set_yaml이 기본 허용 키 외에 추가로 쓸 수 있는 최상위 키입니다. 신뢰 경계 키는 무시됩니다."
} }
}, },
@@ -29,11 +29,11 @@
"title": "HA-MCP Bestands- & YAML-hulpmiddelen", "title": "HA-MCP Bestands- & YAML-hulpmiddelen",
"description": "Configureer de geprivilegieerde bestands- en YAML-bewerkingsservices die worden gebruikt door de opt-in bestands-/YAML-hulpmiddelen van ha-mcp. Deze instellingen verschijnen ook in de eigen instellingen-UI van de ha-mcp server en worden direct toegepast, zonder herstart. Een niet-overbrugbare blokkade weigert nog steeds gevoelige paden (bijv. .storage) en trust-boundary sleutels (homeassistant, http, frontend, lovelace).", "description": "Configureer de geprivilegieerde bestands- en YAML-bewerkingsservices die worden gebruikt door de opt-in bestands-/YAML-hulpmiddelen van ha-mcp. Deze instellingen verschijnen ook in de eigen instellingen-UI van de ha-mcp server en worden direct toegepast, zonder herstart. Een niet-overbrugbare blokkade weigert nog steeds gevoelige paden (bijv. .storage) en trust-boundary sleutels (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Extra bestandsmappen", "allowed_dirs": "Extra bestandspaden",
"extra_yaml_keys": "Extra YAML-schrijfsleutels" "extra_yaml_keys": "Extra YAML-schrijfsleutels"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Mappen relatief aan de configuratiemap, elk met lees- en schrijfrechten (bijv. pyscript). Traversale en buiten-configuratie ingangen worden genegeerd.", "allowed_dirs": "Paden relatief ten opzichte van deconfiguratiemap, inclusief exacte bestandsnamen zoals sensor.yaml, of paden onder /share, /media, /ssl en /backup. Elk opgegeven pad en alles daaronder krijgt lees- en schrijfrechten; voer elk pad in als een apart lijstitem. Padtraversatie en andere niet-toegestane paden worden genegeerd.",
"extra_yaml_keys": "Top-level sleutels die ha_config_set_yaml mag schrijven naast de ingebouwde, voor YAML-first integraties op deze installatie (bijv. alert2). Trust-boundary sleutels worden genegeerd." "extra_yaml_keys": "Top-level sleutels die ha_config_set_yaml mag schrijven naast de ingebouwde, voor YAML-first integraties op deze installatie (bijv. alert2). Trust-boundary sleutels worden genegeerd."
} }
}, },
@@ -29,11 +29,11 @@
"title": "Narzędzia plików i YAML HA-MCP", "title": "Narzędzia plików i YAML HA-MCP",
"description": "Skonfiguruj uprzywilejowane usługi edycji plików i YAML używane przez opcjonalne narzędzia plików/YAML ha-mcp. Te ustawienia pojawiają się również w interfejsie ustawień serwera ha-mcp i są stosowane na żywo, bez restartu. Nienadpisywalna blokada nadal blokuje wrażliwe ścieżki (np. .storage) i klucze graniczne zaufania (homeassistant, http, frontend, lovelace).", "description": "Skonfiguruj uprzywilejowane usługi edycji plików i YAML używane przez opcjonalne narzędzia plików/YAML ha-mcp. Te ustawienia pojawiają się również w interfejsie ustawień serwera ha-mcp i są stosowane na żywo, bez restartu. Nienadpisywalna blokada nadal blokuje wrażliwe ścieżki (np. .storage) i klucze graniczne zaufania (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Dodatkowe katalogi plików", "allowed_dirs": "Dodatkowe ścieżki plików",
"extra_yaml_keys": "Dodatkowe klucze zapisu YAML" "extra_yaml_keys": "Dodatkowe klucze zapisu YAML"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Katalogi względem katalogu konfiguracyjnego, każdy z uprawnieniami do odczytu i zapisu (np. pyscript). Wpisy poza konfiguracją i przechodzenie przez katalogi są odrzucane.", "allowed_dirs": "Ścieżki względne do katalogu konfiguracyjnego, w tym dokładne nazwy plików, takie jak sensor.yaml, lub ścieżki w katalogach /share, /media, /ssl i /backup. Każdy wpis otrzymuje uprawnienia do odczytu i zapisu dla danej ścieżki oraz wszystkiego, co się w niej znajduje; wpisz każdą ścieżkę jako oddzielny element listy. Przechodzenie w górę drzewa katalogów (traversal) i inne niedozwolone ścieżki są odrzucane.",
"extra_yaml_keys": "Klucze najwyższego poziomu, które ha_config_set_yaml może zapisywać oprócz wbudowanych, dla integracji opartych na YAML w tej instalacji (np. alert2). Klucze graniczne zaufania są odrzucane." "extra_yaml_keys": "Klucze najwyższego poziomu, które ha_config_set_yaml może zapisywać oprócz wbudowanych, dla integracji opartych na YAML w tej instalacji (np. alert2). Klucze graniczne zaufania są odrzucane."
} }
}, },
@@ -29,11 +29,11 @@
"title": "Файловые инструменты и инструменты YAML HA-MCP", "title": "Файловые инструменты и инструменты YAML HA-MCP",
"description": "Настройка привилегированных служб для работы с файлами и редактирования YAML, которые используются отключёнными по умолчанию файловыми инструментами и инструментами YAML в ha-mcp. Эти параметры также отображаются в собственном интерфейсе настроек сервера ha-mcp и применяются сразу, без перезапуска. Неотключаемый базовый запрет по-прежнему блокирует чувствительные пути (например, .storage) и ключи границы доверия (homeassistant, http, frontend, lovelace).", "description": "Настройка привилегированных служб для работы с файлами и редактирования YAML, которые используются отключёнными по умолчанию файловыми инструментами и инструментами YAML в ha-mcp. Эти параметры также отображаются в собственном интерфейсе настроек сервера ha-mcp и применяются сразу, без перезапуска. Неотключаемый базовый запрет по-прежнему блокирует чувствительные пути (например, .storage) и ключи границы доверия (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Дополнительные файловые каталоги", "allowed_dirs": "Дополнительные пути к файлам",
"extra_yaml_keys": "Дополнительные YAML-ключи для записи" "extra_yaml_keys": "Дополнительные YAML-ключи для записи"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Каталоги относительно каталога конфигурации, каждому предоставляется доступ на чтение и запись (например, pyscript). Записи с обходом пути и вне каталога конфигурации отбрасываются.", "allowed_dirs": "Пути относительно каталога конфигурации, включая точные имена файлов, такие как sensor.yaml, или пути в директориях /share, /media, /ssl и /backup. Для каждого элемента предоставляется доступ на чтение и запись к самому пути и всему, что находится в нем; вводите каждый путь как отдельный элемент списка. Обход каталогов и другие запрещенные пути отбрасываются.",
"extra_yaml_keys": "Верхнеуровневые ключи, которые ha_config_set_yaml может записывать вдобавок к встроенным, — для YAML-ориентированных интеграций на этой установке (например, alert2). Ключи границы доверия отбрасываются." "extra_yaml_keys": "Верхнеуровневые ключи, которые ha_config_set_yaml может записывать вдобавок к встроенным, — для YAML-ориентированных интеграций на этой установке (например, alert2). Ключи границы доверия отбрасываются."
} }
}, },
@@ -29,11 +29,11 @@
"title": "HA-MCP Fil- & YAML-verktyg", "title": "HA-MCP Fil- & YAML-verktyg",
"description": "Konfigurera de privilegierade fil- och YAML-redigeringstjänsterna som används av ha-mcp:s valfria fil-/YAML-verktyg. Dessa inställningar visas också i ha-mcp-serverns eget inställningsgränssnitt och tillämpas direkt, utan omstart. En icke-överskridbar spärr blockerar fortfarande känsliga sökvägar (t.ex. .storage) och nycklar för förtroendegränser (homeassistant, http, frontend, lovelace).", "description": "Konfigurera de privilegierade fil- och YAML-redigeringstjänsterna som används av ha-mcp:s valfria fil-/YAML-verktyg. Dessa inställningar visas också i ha-mcp-serverns eget inställningsgränssnitt och tillämpas direkt, utan omstart. En icke-överskridbar spärr blockerar fortfarande känsliga sökvägar (t.ex. .storage) och nycklar för förtroendegränser (homeassistant, http, frontend, lovelace).",
"data": { "data": {
"allowed_dirs": "Extra filkataloger", "allowed_dirs": "Extra filvägar",
"extra_yaml_keys": "Extra YAML-skrivnycklar" "extra_yaml_keys": "Extra YAML-skrivnycklar"
}, },
"data_description": { "data_description": {
"allowed_dirs": "Kataloger i förhållande till konfigurationskatalogen, var och en beviljas läs- och skrivrättigheter (t.ex. pyscript). Genomgång och poster utanför konfigurationen ignoreras.", "allowed_dirs": "Sökvägar relativt konfigurationskatalogen, inklusive exakta filnamn som sensor.yaml, eller sökvägar under /share, /media, /ssl och /backup. Varje post ges läs- och skrivbehörighet för den sökvägen och allt under den; ange varje sökväg som ett separat listobjekt. Sökordsbläddring (traversal) och andra otillåtna sökvägar tas bort.",
"extra_yaml_keys": "Toppnivånycklar som ha_config_set_yaml får skriva utöver de inbyggda, för YAML-först-integrationer på denna installation (t.ex. alert2). Nycklar för förtroendegränser ignoreras." "extra_yaml_keys": "Toppnivånycklar som ha_config_set_yaml får skriva utöver de inbyggda, för YAML-först-integrationer på denna installation (t.ex. alert2). Nycklar för förtroendegränser ignoreras."
} }
}, },
@@ -29,11 +29,11 @@
"title": "HA-MCP 文件与 YAML 工具", "title": "HA-MCP 文件与 YAML 工具",
"description": "配置 ha-mcp 可选文件/YAML 工具所使用的特权文件和 YAML 编辑服务。这些设置也会出现在 ha-mcp 服务器自身的设置界面中,并实时生效,无需重启。不可覆盖的拒绝底线仍会阻止敏感路径(例如 .storage)和信任边界键(homeassistant、http、frontend、lovelace)。", "description": "配置 ha-mcp 可选文件/YAML 工具所使用的特权文件和 YAML 编辑服务。这些设置也会出现在 ha-mcp 服务器自身的设置界面中,并实时生效,无需重启。不可覆盖的拒绝底线仍会阻止敏感路径(例如 .storage)和信任边界键(homeassistant、http、frontend、lovelace)。",
"data": { "data": {
"allowed_dirs": "额外的文件目录", "allowed_dirs": "额外文件路径",
"extra_yaml_keys": "额外的 YAML 可写键" "extra_yaml_keys": "额外的 YAML 可写键"
}, },
"data_description": { "data_description": {
"allowed_dirs": "相对于配置目录的目录,每个目录都授予读写权限(例如 pyscript)。路径穿越以及配置目录之外的条目会被丢弃。", "allowed_dirs": "相对于配置目录的路径,包括诸如 sensor.yaml 的确切文件名,或 /share、/media、/ssl 和 /backup 下的路径。每个条目均被授予对该路径及其中所有内容的读写权限;每个路径请作为一个单独的列表项输入。将丢弃目录遍历及其他不允许的路径。",
"extra_yaml_keys": "除内置键外,ha_config_set_yaml 还可写入的顶层键,适用于本安装中以 YAML 为主的集成(例如 alert2)。信任边界键会被丢弃。" "extra_yaml_keys": "除内置键外,ha_config_set_yaml 还可写入的顶层键,适用于本安装中以 YAML 为主的集成(例如 alert2)。信任边界键会被丢弃。"
} }
}, },
+92 -17
View File
@@ -5647,11 +5647,23 @@ async def _call_service_prep(
domain, so it holds no matter which path reaches this function. domain, so it holds no matter which path reaches this function.
2. **ServiceNotFound** before dispatch, so an unknown service is a clean 2. **ServiceNotFound** before dispatch, so an unknown service is a clean
``SERVICE_NOT_FOUND`` and never a landed-but-unreported write. ``SERVICE_NOT_FOUND`` and never a landed-but-unreported write.
3. Pre-state capture for each ``entity_id`` (a synchronous in-memory read). 3. Pre-state capture for each ``entity_id`` (a synchronous in-memory read). A
target whose captured state is ``None`` — absent from the state machine, so
it structurally cannot ever emit a ``state_changed`` for this dispatch — is
excluded from the wait entirely (:func:`_confirmable_entity_ids`); waiting on
it would only burn the full ``timeout`` to learn what the pre-state already
proved. An ``"unavailable"`` target stays IN the wait (unlike a nonexistent
one, it can legitimately reconnect and transition mid-dispatch — excluding it
too would silently miss that), so ``should_confirm`` itself stays keyed off
the full ``entity_ids`` (intent to confirm), not the narrower confirmable
subset — a ``validate_first=False`` caller that intentionally skips the
not-found/unavailable error mapping still needs ``partial=True`` on a
genuinely-excluded target, not a bare unconfirmed-but-not-partial result.
4. Register the expected-aware ``EVENT_STATE_CHANGED`` waiter BEFORE the dispatch 4. Register the expected-aware ``EVENT_STATE_CHANGED`` waiter BEFORE the dispatch
(D5) so a fast entity's event can't arrive before the listener exists. The (D5) so a fast entity's event can't arrive before the listener exists, scoped
waiter confirms only on reaching the server's ``expected_state`` hint (skipping to only the confirmable targets from step 3. The waiter confirms only on
intermediate/noise events); a ``None`` hint keeps any-first-event confirmation. reaching the server's ``expected_state`` hint (skipping intermediate/noise
events); a ``None`` hint keeps any-first-event confirmation.
5. Fire exactly ONE ``async_call`` (``blocking=True``); flip ``dispatched`` 5. Fire exactly ONE ``async_call`` (``blocking=True``); flip ``dispatched``
immediately after so a post-dispatch problem is never retried as a failed immediately after so a post-dispatch problem is never retried as a failed
call (D3/D9). call (D3/D9).
@@ -5695,22 +5707,32 @@ async def _call_service_prep(
wait = msg.get("wait", True) wait = msg.get("wait", True)
timeout = msg.get("timeout", CALL_SERVICE_DEFAULT_TIMEOUT) timeout = msg.get("timeout", CALL_SERVICE_DEFAULT_TIMEOUT)
return_response = msg.get("return_response", False) return_response = msg.get("return_response", False)
should_confirm = bool(wait and entity_ids)
# The server's confirmation HINT (``_SERVICE_TO_STATE.get(service)``), applied to # The server's confirmation HINT (``_SERVICE_TO_STATE.get(service)``), applied to
# every confirmation target. Absent / None keeps any-first-event confirmation. # every confirmation target. Absent / None keeps any-first-event confirmation.
expected_state = msg.get("expected_state") expected_state = msg.get("expected_state")
expected_by_entity = dict.fromkeys(entity_ids, expected_state) expected_by_entity = dict.fromkeys(entity_ids, expected_state)
# should_confirm stays keyed off the full entity_ids (intent to confirm) — see
# the docstring's step 3 for why this must NOT narrow to the confirmable subset.
should_confirm = bool(wait and entity_ids)
# 3. Pre-state capture (synchronous in-memory reads, guarded against drift). # 3. Pre-state capture (synchronous in-memory reads, guarded against drift).
pre = {eid: _state_as_dict(_state_get(hass, eid)) for eid in entity_ids} pre = {eid: _state_as_dict(_state_get(hass, eid)) for eid in entity_ids}
# Only a target whose pre-dispatch state proves it can possibly report a
# confirming event is worth actually waiting on (see
# ``_confirmable_entity_ids``) — a target absent from the state machine can
# never emit one, so waiting on it is certain to burn the full ``timeout`` for
# no new information; the server reads the certain ``None`` old_state straight
# off the transition instead.
confirmable_entity_ids = _confirmable_entity_ids(entity_ids, pre)
# 4. Register-before-fire (D5): only when there is something to confirm. # 4. Register-before-fire (D5): only when there is something worth confirming.
evt: Any = None evt: Any = None
captured: dict[str, Any] = {} captured: dict[str, Any] = {}
unsub: Any = None unsub: Any = None
if should_confirm: if should_confirm and confirmable_entity_ids:
evt, captured, unsub = _register_transition_waiter( evt, captured, unsub = _register_transition_waiter(
hass, set(entity_ids), expected_by_entity hass, set(confirmable_entity_ids), expected_by_entity
) )
# 5. Dispatch exactly once. 6. Immediate-match + bounded wait. 7. Build the diff. # 5. Dispatch exactly once. 6. Immediate-match + bounded wait. 7. Build the diff.
@@ -5729,9 +5751,13 @@ async def _call_service_prep(
return_response=return_response, return_response=return_response,
) )
dispatched = True dispatched = True
if should_confirm: # ``evt`` is None when nothing was worth waiting on (should_confirm was
# True but every target was excluded as unconfirmable) — there is then
# nothing that could ever confirm, so skip the wait outright rather than
# awaiting an event that was never registered to fire.
if should_confirm and evt is not None:
await _await_confirmation( await _await_confirmation(
hass, entity_ids, expected_by_entity, captured, evt, timeout hass, confirmable_entity_ids, expected_by_entity, captured, evt, timeout
) )
result = _build_call_service_result( result = _build_call_service_result(
hass, hass,
@@ -5764,6 +5790,26 @@ async def _call_service_prep(
return {"result": result} return {"result": result}
def _confirmable_entity_ids(entity_ids: list[str], pre: Mapping[str, Any]) -> list[str]:
"""Targets whose pre-dispatch state proves they can possibly confirm.
A target absent from the state machine (``pre[eid] is None``) can never emit a
confirming ``state_changed`` for this dispatch — HA no-ops a service call for
an entity id that matches nothing, and nothing will register that id mid-call
either. Excluding it from the wait lets the server read the certain outcome
straight off the transition's ``None`` ``old_state`` instead of burning the
full timeout to learn nothing new.
Deliberately NOT excluded: a target whose captured state is ``"unavailable"``.
Unlike a nonexistent id, an unavailable entity can legitimately reconnect and
transition during the blocking dispatch (the very case ``ENTITY_UNAVAILABLE``
exists to distinguish from a real failure would itself go undetected if the
listener were never registered) — so it stays in the wait and is judged by
whether it actually confirmed, not excluded upfront.
"""
return [eid for eid in entity_ids if pre.get(eid) is not None]
def _guard_call_service_target(hass: HomeAssistant, domain: str, service: str) -> None: def _guard_call_service_target(hass: HomeAssistant, domain: str, service: str) -> None:
"""Pre-dispatch refusals for ``call_service`` — raise BEFORE any dispatch. """Pre-dispatch refusals for ``call_service`` — raise BEFORE any dispatch.
@@ -5953,6 +5999,9 @@ def _build_call_service_result(
_call_service_transition(eid, pre.get(eid), _post_state(hass, eid, captured)) _call_service_transition(eid, pre.get(eid), _post_state(hass, eid, captured))
for eid in entity_ids for eid in entity_ids
] ]
# Against the FULL entity_ids, not just the confirmable subset: an excluded
# (nonexistent) target can never land in captured, so this naturally stays
# False whenever one is present — exactly right, since it never confirmed.
confirmed = bool(should_confirm and set(entity_ids) <= set(captured)) confirmed = bool(should_confirm and set(entity_ids) <= set(captured))
result: dict[str, Any] = { result: dict[str, Any] = {
"domain": domain, "domain": domain,
@@ -6155,19 +6204,36 @@ def _bulk_op_record(
``pre`` is the synchronous in-memory pre-state per target; ``expected_by_entity`` ``pre`` is the synchronous in-memory pre-state per target; ``expected_by_entity``
maps every target to this op's confirmation hint (``_SERVICE_TO_STATE``) so the maps every target to this op's confirmation hint (``_SERVICE_TO_STATE``) so the
waiter + immediate-match key off it; ``dispatched`` / ``error`` / ``response`` waiter + immediate-match key off it; ``dispatched`` / ``error`` / ``response``
start empty and are filled during dispatch; ``should_confirm`` is true only when start empty and are filled during dispatch. ``confirmable_entity_ids`` excludes
the batch is waiting AND this op names targets to confirm. ONLY a target whose captured pre-state is ``None`` (nonexistent) — it can never
emit a confirming event, so it is never worth the shared wait (see
``_confirmable_entity_ids``). Deliberately NOT excluded from it: a target
already ``"unavailable"``, which can legitimately reconnect and confirm
mid-dispatch. ``should_confirm`` stays intent-level (``bool(wait and
entity_ids)`` — the FULL list, not the confirmable subset): a
``validate_first=False`` caller that skips the not-found/unavailable error
mapping still needs ``partial=True`` on a genuinely-excluded target, not a
bare unconfirmed-but-not-partial result.
""" """
entity_ids = list(op.get("entity_ids") or []) entity_ids = list(op.get("entity_ids") or [])
expected_state = op.get("expected_state") expected_state = op.get("expected_state")
pre = {eid: _state_as_dict(_state_get(hass, eid)) for eid in entity_ids}
confirmable_entity_ids = _confirmable_entity_ids(entity_ids, pre)
return { return {
"domain": op["domain"], "domain": op["domain"],
"service": op["service"], "service": op["service"],
"service_data": op.get("service_data") or {}, "service_data": op.get("service_data") or {},
"entity_ids": entity_ids, "entity_ids": entity_ids,
"confirmable_entity_ids": confirmable_entity_ids,
"expected_by_entity": dict.fromkeys(entity_ids, expected_state), "expected_by_entity": dict.fromkeys(entity_ids, expected_state),
# Intent-level (full entity_ids), NOT the confirmable subset — mirrors
# ``_call_service_prep``'s should_confirm: a validate_first=False caller
# that intentionally skips the not-found/unavailable error mapping still
# needs partial=True on a genuinely-excluded target, not a bare
# unconfirmed-but-not-partial result. confirmable_entity_ids scopes ONLY
# which targets are actually worth registering a listener / waiting for.
"should_confirm": bool(wait and entity_ids), "should_confirm": bool(wait and entity_ids),
"pre": {eid: _state_as_dict(_state_get(hass, eid)) for eid in entity_ids}, "pre": pre,
"evt": None, "evt": None,
"captured": {}, "captured": {},
"dispatched": False, "dispatched": False,
@@ -6210,9 +6276,9 @@ def _bulk_register_all(hass: HomeAssistant, ops: list[dict[str, Any]]) -> list[A
unsubs: list[Any] = [] unsubs: list[Any] = []
try: try:
for op in ops: for op in ops:
if op["should_confirm"]: if op["should_confirm"] and op["confirmable_entity_ids"]:
evt, captured, unsub = _register_transition_waiter( evt, captured, unsub = _register_transition_waiter(
hass, set(op["entity_ids"]), op["expected_by_entity"] hass, set(op["confirmable_entity_ids"]), op["expected_by_entity"]
) )
op["evt"] = evt op["evt"] = evt
op["captured"] = captured op["captured"] = captured
@@ -6267,7 +6333,10 @@ def _bulk_match_immediate(hass: HomeAssistant, ops: list[dict[str, Any]]) -> Non
for op in ops: for op in ops:
if op["should_confirm"] and op["dispatched"]: if op["should_confirm"] and op["dispatched"]:
_match_immediate( _match_immediate(
hass, op["entity_ids"], op["expected_by_entity"], op["captured"] hass,
op["confirmable_entity_ids"],
op["expected_by_entity"],
op["captured"],
) )
@@ -6289,7 +6358,10 @@ async def _bulk_wait_all(ops: list[dict[str, Any]], timeout: float) -> None:
for op in ops for op in ops
if op["should_confirm"] if op["should_confirm"]
and op["dispatched"] and op["dispatched"]
and not (set(op["entity_ids"]) <= set(op["captured"])) # evt is None when nothing was worth waiting on for this op (every
# target was excluded as unconfirmable) — nothing could ever set it.
and op["evt"] is not None
and not (set(op["confirmable_entity_ids"]) <= set(op["captured"]))
] ]
if not waiters: if not waiters:
return return
@@ -6330,6 +6402,9 @@ def _build_bulk_op_result(hass: HomeAssistant, op: Mapping[str, Any]) -> dict[st
) )
for eid in entity_ids for eid in entity_ids
] ]
# Against the FULL entity_ids, not just the confirmable subset: an excluded
# (nonexistent) target can never land in captured, so this naturally stays
# False whenever one is present — exactly right, since it never confirmed.
confirmed = bool(should_confirm and dispatched and set(entity_ids) <= set(captured)) confirmed = bool(should_confirm and dispatched and set(entity_ids) <= set(captured))
result: dict[str, Any] = { result: dict[str, Any] = {
"domain": op["domain"], "domain": op["domain"],
@@ -1,63 +1,63 @@
function t(t,e,i,o){var n,a=arguments.length,s=a<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,i,o);else for(var r=t.length-1;r>=0;r--)(n=t[r])&&(s=(a<3?n(s):a>3?n(e,i,s):n(e,i))||s);return a>3&&s&&Object.defineProperty(e,i,s),s}"function"==typeof SuppressedError&&SuppressedError; function t(t,e,i,o){var a,n=arguments.length,s=n<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,i,o);else for(var r=t.length-1;r>=0;r--)(a=t[r])&&(s=(n<3?a(s):n>3?a(e,i,s):a(e,i))||s);return n>3&&s&&Object.defineProperty(e,i,s),s}"function"==typeof SuppressedError&&SuppressedError;
/** /**
* @license * @license
* Copyright 2019 Google LLC * Copyright 2019 Google LLC
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
const e=globalThis,i=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,o=Symbol(),n=new WeakMap;let a=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==o)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(i&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=n.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&n.set(e,t))}return t}toString(){return this.cssText}};const s=(t,...e)=>{const i=1===t.length?t[0]:e.reduce(((e,i,o)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[o+1]),t[0]);return new a(i,t,o)},r=i?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new a("string"==typeof t?t:t+"",void 0,o))(e)})(t):t const e=globalThis,i=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,o=Symbol(),a=new WeakMap;let n=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==o)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(i&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=a.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&a.set(e,t))}return t}toString(){return this.cssText}};const s=(t,...e)=>{const i=1===t.length?t[0]:e.reduce(((e,i,o)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[o+1]),t[0]);return new n(i,t,o)},r=i?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new n("string"==typeof t?t:t+"",void 0,o))(e)})(t):t
/** /**
* @license * @license
* Copyright 2017 Google LLC * Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/,{is:l,defineProperty:c,getOwnPropertyDescriptor:d,getOwnPropertyNames:h,getOwnPropertySymbols:u,getPrototypeOf:m}=Object,p=globalThis,_=p.trustedTypes,g=_?_.emptyScript:"",f=p.reactiveElementPolyfillSupport,b=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?g:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!l(t,e),w={attribute:!0,type:String,converter:v,reflect:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),p.litPropertyMetadata??=new WeakMap;let x=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=w){if(e.state&&(e.attribute=!1),this._$Ei(),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),o=this.getPropertyDescriptor(t,i,e);void 0!==o&&c(this.prototype,t,o)}}static getPropertyDescriptor(t,e,i){const{get:o,set:n}=d(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get(){return o?.call(this)},set(e){const a=o?.call(this);n.call(this,e),this.requestUpdate(t,a,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??w}static _$Ei(){if(this.hasOwnProperty(b("elementProperties")))return;const t=m(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(b("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(b("properties"))){const t=this.properties,e=[...h(t),...u(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(r(t))}else void 0!==t&&e.push(r(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$Eg=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((t=>t(this)))}addController(t){(this._$ES??=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$ES?.splice(this._$ES.indexOf(t)>>>0,1)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((t,o)=>{if(i)t.adoptedStyleSheets=o.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet));else for(const i of o){const o=document.createElement("style"),n=e.litNonce;void 0!==n&&o.setAttribute("nonce",n),o.textContent=i.cssText,t.appendChild(o)}})(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$ES?.forEach((t=>t.hostConnected?.()))}enableUpdating(t){}disconnectedCallback(){this._$ES?.forEach((t=>t.hostDisconnected?.()))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e){const i=this.constructor.elementProperties.get(t),o=this.constructor._$Eu(t,i);if(void 0!==o&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==n?this.removeAttribute(o):this.setAttribute(o,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,o=i._$Eh.get(t);if(void 0!==o&&this._$Em!==o){const t=i.getPropertyOptions(o),n="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=o,this[o]=n.fromAttribute(e,t.type),this._$Em=null}}requestUpdate(t,e,i,o=!1,n){if(void 0!==t){if(i??=this.constructor.getPropertyOptions(t),!(i.hasChanged??y)(o?n:this[t],e))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$Eg=this._$EP())}C(t,e,i){this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$Em!==t&&(this._$Ej??=new Set).add(t)}async _$EP(){this.isUpdatePending=!0;try{await this._$Eg}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t)!0!==i.wrapped||this._$AL.has(e)||void 0===this[e]||this.C(e,this[e],iLine truncated */,{is:l,defineProperty:c,getOwnPropertyDescriptor:d,getOwnPropertyNames:h,getOwnPropertySymbols:u,getPrototypeOf:p}=Object,m=globalThis,_=m.trustedTypes,f=_?_.emptyScript:"",g=m.reactiveElementPolyfillSupport,b=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?f:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!l(t,e),w={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),m.litPropertyMetadata??=new WeakMap;let x=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=w){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),o=this.getPropertyDescriptor(t,i,e);void 0!==o&&c(this.prototype,t,o)}}static getPropertyDescriptor(t,e,i){const{get:o,set:a}=d(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:o,set(e){const n=o?.call(this);a?.call(this,e),this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??w}static _$Ei(){if(this.hasOwnProperty(b("elementProperties")))return;const t=p(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(b("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(b("properties"))){const t=this.properties,e=[...h(t),...u(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(r(t))}else void 0!==t&&e.push(r(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((t=>t(this)))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((t,o)=>{if(i)t.adoptedStyleSheets=o.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet));else for(const i of o){const o=document.createElement("style"),a=e.litNonce;void 0!==a&&o.setAttribute("nonce",a),o.textContent=i.cssText,t.appendChild(o)}})(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach((t=>t.hostConnected?.()))}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach((t=>t.hostDisconnected?.()))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),o=this.constructor._$Eu(t,i);if(void 0!==o&&!0===i.reflect){const a=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==a?this.removeAttribute(o):this.setAttribute(o,a),this._$Em=null}}_$AK(t,e){const i=this.constructor,o=i._$Eh.get(t);if(void 0!==o&&this._$Em!==o){const t=i.getPropertyOptions(o),a="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=o;const n=a.fromAttribute(e,t.type);this[o]=n??this._$Ej?.get(o)??n,this._$Em=null}}requestUpdate(t,e,i,o=!1,a){if(void 0!==t){const n=this.constructor;if(!1===o&&(a=this[t]),i??=n.getPropertyOptions(t),!((i.hasChanged??y)(a,e)||i.useDefault&&i.reflect&&a===this._$Ej?.get(t)&&!this.hasAttribute(n._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:o,wrapped:a},n){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,n??e??this[t]),!0!==a||void 0!==n)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===o&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scLine truncated
/** /**
* @license * @license
* Copyright 2017 Google LLC * Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
const k=globalThis,T=k.trustedTypes,S=T?T.createPolicy("lit-html",{createHTML:t=>t}):void 0,M="$lit$",D=`lit$${(Math.random()+"").slice(9)}$`,C="?"+D,A=`<${C}>`,P=document,E=()=>P.createComment(""),L=t=>null===t||"object"!=typeof t&&"function"!=typeof t,$=Array.isArray,z="[ \t\n\f\r]",O=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,V=/-->/g,H=/>/g,R=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),I=/'/g,N=/"/g,F=/^(?:script|style|textarea|title)$/i,W=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),B=W(1),j=W(2),U=Symbol.for("lit-noChange"),Y=Symbol.for("lit-nothing"),q=new WeakMap,Z=P.createTreeWalker(P,129);function X(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(e):e}const K=(t,e)=>{const i=t.length-1,o=[];let n,a=2===e?"<svg>":"",s=O;for(let e=0;e<i;e++){const i=t[e];let r,l,c=-1,d=0;for(;d<i.length&&(s.lastIndex=d,l=s.exec(i),null!==l);)d=s.lastIndex,s===O?"!--"===l[1]?s=V:void 0!==l[1]?s=H:void 0!==l[2]?(F.test(l[2])&&(n=RegExp("</"+l[2],"g")),s=R):void 0!==l[3]&&(s=R):s===R?">"===l[0]?(s=n??O,c=-1):void 0===l[1]?c=-2:(c=s.lastIndex-l[2].length,r=l[1],s=void 0===l[3]?R:'"'===l[3]?N:I):s===N||s===I?s=R:s===V||s===H?s=O:(s=R,n=void 0);const h=s===R&&t[e+1].startsWith("/>")?" ":"";a+=s===O?i+A:c>=0?(o.push(r),i.slice(0,c)+M+i.slice(c)+D+h):i+D+(-2===c?e:h)}return[X(t,a+(t[i]||"<?>")+(2===e?"</svg>":"")),o]};class G{constructor({strings:t,_$litType$:e},i){let o;this.parts=[];let n=0,a=0;const s=t.length-1,r=this.parts,[l,c]=K(t,e);if(this.el=G.createElement(l,i),Z.currentNode=this.el.content,2===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(o=Z.nextNode())&&r.length<s;){if(1===o.nodeType){if(o.hasAttributes())for(const t of o.getAttributeNames())if(t.endsWith(M)){const e=c[a++],i=o.getAttribute(t).split(D),s=/([.?@])?(.*)/.exec(e);r.push({type:1,index:n,name:s[2],strings:i,ctor:"."===s[1]?it:"?"===s[1]?ot:"@"===s[1]?nt:et}),o.removeAttribute(t)}else t.startsWith(D)&&(r.push({type:6,index:n}),o.removeAttribute(t));if(F.test(o.tagName)){const t=o.textContent.split(D),e=t.length-1;if(e>0){o.textContent=T?T.emptyScript:"";for(let i=0;i<e;i++)o.append(t[i],E()),Z.nextNode(),r.push({type:2,index:++n});o.append(t[e],E())}}}else if(8===o.nodeType)if(o.data===C)r.push({type:2,index:n});else{let t=-1;for(;-1!==(t=o.data.indexOf(D,t+1));)r.push({type:7,index:n}),t+=D.length-1}n++}}static createElement(t,e){const i=P.createElement("template");return i.innerHTML=t,i}}function Q(t,e,i=t,o){if(e===U)return e;let n=void 0!==o?i._$Co?.[o]:i._$Cl;const a=L(e)?void 0:e._$litDirective$;return n?.constructor!==a&&(n?._$AO?.(!1),void 0===a?n=void 0:(n=new a(t),n._$AT(t,i,o)),void 0!==o?(i._$Co??=[])[o]=n:i._$Cl=n),void 0!==n&&(e=Q(t,n._$AS(t,e.values),n,o)),e}class J{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:e},parts:i}=this._$AD,o=(t?.creationScope??P).importNode(e,!0);Z.currentNode=o;let n=Z.nextNode(),a=0,s=0,r=i[0];for(;void 0!==r;){if(a===r.index){let e;2===r.type?e=new tt(n,n.nextSibling,this,t):1===r.type?e=new r.ctor(n,r.name,r.strings,this,t):6===r.type&&(e=new at(n,this,t)),this._$AV.push(e),r=i[++s]}a!==r?.index&&(n=Z.nextNode(),a++)}return Z.currentNode=P,o}p(t){let e=0;for(const i of this._$AV)void 0!==i&&(void 0!==i.strings?(i._$AI(t,i,e),e+=i.strings.length-2):i._$AI(t[e])),e++}}class tt{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,i,o){this.type=2,this._$AH=Y,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=i,this.options=o,this._$Cv=o?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const e=this._$AM;return void 0!==e&&11===t?.nodeType&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=Q(this,t,e),L(t)?t===Y||null==t||""===t?(this._$AH!==Y&&this._$AR(),this._$AH=Y):t!==this._$AH&&t!==U&&this._(t):void 0!==t._$litType$?this.g(t):void 0!==t.nodeType?this.$(t):(t=>$(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.T(t):this._(t)}k(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}$(t){this._$AH!==t&&(this._$AR(),this._$AH=this.k(t))}_(t){this._$AH!==Y&&L(this._$AH)?this._$AA.nextSibling.data=t:this.$(P.createTextNode(t)),this._$AH=t}g(t){const{values:e,_$litType$:i}=t,o="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=G.createElement(X(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===o)this._$AH.p(e);else{const t=new J(o,this),i=t.u(this.options);t.p(e),this.$(i),this._$AH=t}}_$AC(t){let e=q.get(t.strings);return void 0===e&&q.set(t.strings,e=new G(t)),e}T(t){$(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,o=0;for(const n of t)o===e.length?e.push(i=new tt(this.k(E()),this.k(E()),this,this.options)):i=e[o],i._$AI(n),o++;o<e.length&&(this._$AR(i&&i._$AB.nextSibling,o),e.length=o)}_$AR(t=this._$AA.nextSibling,e){foLine truncated const k=globalThis,S=k.trustedTypes,T=S?S.createPolicy("lit-html",{createHTML:t=>t}):void 0,M="$lit$",D=`lit$${Math.random().toFixed(9).slice(2)}$`,C="?"+D,A=`<${C}>`,P=document,E=()=>P.createComment(""),L=t=>null===t||"object"!=typeof t&&"function"!=typeof t,$=Array.isArray,z="[ \t\n\f\r]",O=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,V=/-->/g,H=/>/g,I=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),R=/'/g,F=/"/g,N=/^(?:script|style|textarea|title)$/i,j=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),W=j(1),B=j(2),U=Symbol.for("lit-noChange"),Y=Symbol.for("lit-nothing"),q=new WeakMap,Z=P.createTreeWalker(P,129);function X(t,e){if(!$(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==T?T.createHTML(e):e}const K=(t,e)=>{const i=t.length-1,o=[];let a,n=2===e?"<svg>":3===e?"<math>":"",s=O;for(let e=0;e<i;e++){const i=t[e];let r,l,c=-1,d=0;for(;d<i.length&&(s.lastIndex=d,l=s.exec(i),null!==l);)d=s.lastIndex,s===O?"!--"===l[1]?s=V:void 0!==l[1]?s=H:void 0!==l[2]?(N.test(l[2])&&(a=RegExp("</"+l[2],"g")),s=I):void 0!==l[3]&&(s=I):s===I?">"===l[0]?(s=a??O,c=-1):void 0===l[1]?c=-2:(c=s.lastIndex-l[2].length,r=l[1],s=void 0===l[3]?I:'"'===l[3]?F:R):s===F||s===R?s=I:s===V||s===H?s=O:(s=I,a=void 0);const h=s===I&&t[e+1].startsWith("/>")?" ":"";n+=s===O?i+A:c>=0?(o.push(r),i.slice(0,c)+M+i.slice(c)+D+h):i+D+(-2===c?e:h)}return[X(t,n+(t[i]||"<?>")+(2===e?"</svg>":3===e?"</math>":"")),o]};class G{constructor({strings:t,_$litType$:e},i){let o;this.parts=[];let a=0,n=0;const s=t.length-1,r=this.parts,[l,c]=K(t,e);if(this.el=G.createElement(l,i),Z.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(o=Z.nextNode())&&r.length<s;){if(1===o.nodeType){if(o.hasAttributes())for(const t of o.getAttributeNames())if(t.endsWith(M)){const e=c[n++],i=o.getAttribute(t).split(D),s=/([.?@])?(.*)/.exec(e);r.push({type:1,index:a,name:s[2],strings:i,ctor:"."===s[1]?it:"?"===s[1]?ot:"@"===s[1]?at:et}),o.removeAttribute(t)}else t.startsWith(D)&&(r.push({type:6,index:a}),o.removeAttribute(t));if(N.test(o.tagName)){const t=o.textContent.split(D),e=t.length-1;if(e>0){o.textContent=S?S.emptyScript:"";for(let i=0;i<e;i++)o.append(t[i],E()),Z.nextNode(),r.push({type:2,index:++a});o.append(t[e],E())}}}else if(8===o.nodeType)if(o.data===C)r.push({type:2,index:a});else{let t=-1;for(;-1!==(t=o.data.indexOf(D,t+1));)r.push({type:7,index:a}),t+=D.length-1}a++}}static createElement(t,e){const i=P.createElement("template");return i.innerHTML=t,i}}function Q(t,e,i=t,o){if(e===U)return e;let a=void 0!==o?i._$Co?.[o]:i._$Cl;const n=L(e)?void 0:e._$litDirective$;return a?.constructor!==n&&(a?._$AO?.(!1),void 0===n?a=void 0:(a=new n(t),a._$AT(t,i,o)),void 0!==o?(i._$Co??=[])[o]=a:i._$Cl=a),void 0!==a&&(e=Q(t,a._$AS(t,e.values),a,o)),e}class J{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:e},parts:i}=this._$AD,o=(t?.creationScope??P).importNode(e,!0);Z.currentNode=o;let a=Z.nextNode(),n=0,s=0,r=i[0];for(;void 0!==r;){if(n===r.index){let e;2===r.type?e=new tt(a,a.nextSibling,this,t):1===r.type?e=new r.ctor(a,r.name,r.strings,this,t):6===r.type&&(e=new nt(a,this,t)),this._$AV.push(e),r=i[++s]}n!==r?.index&&(a=Z.nextNode(),n++)}return Z.currentNode=P,o}p(t){let e=0;for(const i of this._$AV)void 0!==i&&(void 0!==i.strings?(i._$AI(t,i,e),e+=i.strings.length-2):i._$AI(t[e])),e++}}class tt{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,i,o){this.type=2,this._$AH=Y,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=i,this.options=o,this._$Cv=o?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const e=this._$AM;return void 0!==e&&11===t?.nodeType&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=Q(this,t,e),L(t)?t===Y||null==t||""===t?(this._$AH!==Y&&this._$AR(),this._$AH=Y):t!==this._$AH&&t!==U&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):(t=>$(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==Y&&L(this._$AH)?this._$AA.nextSibling.data=t:this.T(P.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,o="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=G.createElement(X(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===o)this._$AH.p(e);else{const t=new J(o,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=q.get(t.strings);return void 0===e&&q.set(t.strings,e=new G(t)),e}k(t){$(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,o=0;for(const a of t)o===e.length?e.push(i=new tt(this.O(E()),this.O(E()),this,this.options)):i=e[o],i._$AI(a),o++;o<e.length&&(this._$AR(i&&i._$AB.nextSibling,o),e.length=o)}_$Line truncated
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/let lt=class extends x{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,i)=>{const o=i?.renderBefore??e;let a=o._$litPart$;if(void 0===a){const t=i?.renderBefore??null;o._$litPart$=a=new tt(e.insertBefore(E(),t),t,void 0,i??{})}return a._$AI(t),a})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};lt._$litElement$=!0,lt.finalized=!0,rt.litElementHydrateSupport?.({LitElement:lt});const ct=rt.litElementPolyfillSupport;ct?.({LitElement:lt}),(rt.litElementVersions??=[]).push("4.2.2");
/** /**
* @license * @license
* Copyright 2017 Google LLC * Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
class rt extends x{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,i)=>{const o=i?.renderBefore??e;let n=o._$litPart$;if(void 0===n){const t=i?.renderBefore??null;o._$litPart$=n=new tt(e.insertBefore(E(),t),t,void 0,i??{})}return n._$AI(t),n})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}}rt._$litElement$=!0,rt.finalized=!0,globalThis.litElementHydrateSupport?.({LitElement:rt});const lt=globalThis.litElementPolyfillSupport;lt?.({LitElement:rt}),(globalThis.litElementVersions??=[]).push("4.0.1"); const dt=t=>(e,i)=>{void 0!==i?i.addInitializer((()=>{customElements.define(t,e)})):customElements.define(t,e)}
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/,ht={attribute:!0,type:String,converter:v,reflect:!1,hasChanged:y},ut=(t=ht,e,i)=>{const{kind:o,metadata:a}=i;let n=globalThis.litPropertyMetadata.get(a);if(void 0===n&&globalThis.litPropertyMetadata.set(a,n=new Map),"setter"===o&&((t=Object.create(t)).wrapped=!0),n.set(i.name,t),"accessor"===o){const{name:o}=i;return{set(i){const a=e.get.call(this);e.set.call(this,i),this.requestUpdate(o,a,t,!0,i)},init(e){return void 0!==e&&this.C(o,void 0,t,e),e}}}if("setter"===o){const{name:o}=i;return function(i){const a=this[o];e.call(this,i),this.requestUpdate(o,a,t,!0,i)}}throw Error("Unsupported decorator location: "+o)};function pt(t){return(e,i)=>"object"==typeof i?ut(t,e,i):((t,e,i)=>{const o=e.hasOwnProperty(i);return e.constructor.createProperty(i,t),o?Object.getOwnPropertyDescriptor(e,i):void 0})(t,e,i)
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/}function mt(t){return pt({...t,state:!0,attribute:!1})}
/** /**
* @license * @license
* Copyright 2017 Google LLC * Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
const ct=t=>(e,i)=>{void 0!==i?i.addInitializer((()=>{customElements.define(t,e)})):customElements.define(t,e)}
/** /**
* @license * @license
* Copyright 2017 Google LLC * Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/,dt={attribute:!0,type:String,converter:v,reflect:!1,hasChanged:y},ht=(t=dt,e,i)=>{const{kind:o,metadata:n}=i;let a=globalThis.litPropertyMetadata.get(n);if(void 0===a&&globalThis.litPropertyMetadata.set(n,a=new Map),a.set(i.name,t),"accessor"===o){const{name:o}=i;return{set(i){const n=e.get.call(this);e.set.call(this,i),this.requestUpdate(o,n,t)},init(e){return void 0!==e&&this.C(o,void 0,t),e}}}if("setter"===o){const{name:o}=i;return function(i){const n=this[o];e.call(this,i),this.requestUpdate(o,n,t)}}throw Error("Unsupported decorator location: "+o)};function ut(t){return(e,i)=>"object"==typeof i?ht(t,e,i):((t,e,i)=>{const o=e.hasOwnProperty(i);return e.constructor.createProperty(i,o?{...t,wrapped:!0}:t),o?Object.getOwnPropertyDescriptor(e,i):void 0})(t,e,i) */
function _t(t,e){return(e,i,o)=>((t,e,i)=>(i.configurable=!0,i.enumerable=!0,Reflect.decorate&&"object"!=typeof e&&Object.defineProperty(t,e,i),i))(e,i,{get(){return(e=>e.renderRoot?.querySelector(t)??null)(this)}})}
/** /**
* @license * @license
* Copyright 2017 Google LLC * Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/}function mt(t){return ut({...t,state:!0,attribute:!1})} */const ft=1;class gt{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const pt=(t,e,i)=>(i.configurable=!0,i.enumerable=!0,Reflect.decorate&&"object"!=typeof e&&Object.defineProperty(t,e,i),i)
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/;function _t(t,e){return(i,o,n)=>{const a=e=>e.renderRoot?.querySelector(t)??null;if(e){const{get:t,set:s}="object"==typeof o?i:n??(()=>{const t=Symbol();return{get(){return this[t]},set(e){this[t]=e}}})();return pt(i,o,{get(){if(e){let e=t.call(this);return void 0===e&&(e=a(this),s.call(this,e)),e}return a(this)}})}return pt(i,o,{get(){return a(this)}})}}
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const gt=1;class ft{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}
/** /**
* @license * @license
* Copyright 2018 Google LLC * Copyright 2018 Google LLC
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/const bt=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends ft{constructor(t){if(super(t),t.type!==gt||"class"!==t.name||t.strings?.length>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return" "+Object.keys(t).filter((e=>t[e])).join(" ")+" "}update(t,[e]){if(void 0===this.it){this.it=new Set,void 0!==t.strings&&(this.st=new Set(t.strings.join(" ").split(/\s/).filter((t=>""!==t))));for(const t in e)e[t]&&!this.st?.has(t)&&this.it.add(t);return this.render(e)}const i=t.element.classList;for(const t of this.it)t in e||(i.remove(t),this.it.delete(t));for(const t in e){const o=!!e[t];o===this.it.has(t)||this.st?.has(t)||(o?(i.add(t),this.it.add(t)):(i.remove(t),this.it.delete(t)))}return U}});var vt="M6.59,0.66C8.93,-1.15 11.47,1.06 12.04,4.5C12.47,4.5 12.89,4.62 13.27,4.84C13.79,4.24 14.25,3.42 14.07,2.5C13.65,0.35 16.06,-1.39 18.35,1.58C20.16,3.92 17.95,6.46 14.5,7.03C14.5,7.46 14.39,7.89 14.16,8.27C14.76,8.78 15.58,9.24 16.5,9.06C18.63,8.64 20.38,11.04 17.41,13.34C15.07,15.15 12.53,12.94 11.96,9.5C11.53,9.5 11.11,9.37 10.74,9.15C10.22,9.75 9.75,10.58 9.93,11.5C10.35,13.64 7.94,15.39 5.65,12.42C3.83,10.07 6.05,7.53 9.5,6.97C9.5,6.54 9.63,6.12 9.85,5.74C9.25,5.23 8.43,4.76 7.5,4.94C5.37,5.36 3.62,2.96 6.59,0.66M5,16H7A2,2 0 0,1 9,18V24H7V22H5V24H3V18A2,2 0 0,1 5,16M5,18V20H7V18H5M12.93,16H15L12.07,24H10L12.93,16M18,16H21V18H18V22H21V24H18A2,2 0 0,1 16,22V18A2,2 0 0,1 18,16Z",yt="M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M11,15H13V17H11V15M11,7H13V13H11V7",wt="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z",xt="M7.41,15.41L12,10.83L16.59,15.41L18,14L12,8L6,14L7.41,15.41Z",kt="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z",Tt="M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z",St="M12,11A1,1 0 0,0 11,12A1,1 0 0,0 12,13A1,1 0 0,0 13,12A1,1 0 0,0 12,11M12.5,2C17,2 17.11,5.57 14.75,6.75C13.76,7.24 13.32,8.29 13.13,9.22C13.61,9.42 14.03,9.73 14.35,10.13C18.05,8.13 22.03,8.92 22.03,12.5C22.03,17 18.46,17.1 17.28,14.73C16.78,13.74 15.72,13.3 14.79,13.11C14.59,13.59 14.28,14 13.88,14.34C15.87,18.03 15.08,22 11.5,22C7,22 6.91,18.42 9.27,17.24C10.25,16.75 10.69,15.71 10.89,14.79C10.4,14.59 9.97,14.27 9.65,13.87C5.96,15.85 2,15.07 2,11.5C2,7 5.56,6.89 6.74,9.26C7.24,10.25 8.29,10.68 9.22,10.87C9.41,10.39 9.73,9.97 10.14,9.65C8.15,5.96 8.94,2 12.5,2Z",Mt="M5,2V13H8V22L15,10H11L15,2M17,15H19V17H17V15M17,7H19V13H17V7Z",Dt="M8.5 4.5L5.4 9.5L8.5 14.7L5.2 20.5L3.4 19.6L6.1 14.7L3 9.5L6.7 3.6L8.5 4.5M14.7 4.4L11.6 9.5L14.7 14.5L11.4 20.3L9.6 19.4L12.3 14.5L9.2 9.5L12.9 3.5L14.7 4.4M21 4.4L17.9 9.5L21 14.5L17.7 20.3L15.9 19.4L18.6 14.5L15.5 9.5L19.2 3.5L21 4.4",Ct="M12,3L2,12H5V20H19V12H22L12,3M12,8.75A2.25,2.25 0 0,1 14.25,11A2.25,2.25 0 0,1 12,13.25A2.25,2.25 0 0,1 9.75,11A2.25,2.25 0 0,1 12,8.75M12,15C13.5,15 16.5,15.75 16.5,17.25V18H7.5V17.25C7.5,15.75 10.5,15 12,15Z",At="M13 9H11V7H13V9M13 17H11V11H13V17M5 3H19C20.1 3 21 3.89 21 5V19C21 19.53 20.79 20.04 20.41 20.41C20.04 20.79 19.53 21 19 21H5C4.47 21 3.96 20.79 3.59 20.41C3.21 20.04 3 19.53 3 19V5C3 3.89 3.89 3 5 3M19 19V5H5V19H19Z",Pt="M12,17A2,2 0 0,0 14,15C14,13.89 13.1,13 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V10C4,8.89 4.9,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z",Et="M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10A2,2 0 0,1 6,8H15V6A3,3 0 0,0 12,3A3,3 0 0,0 9,6H7A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,17A2,2 0 0,0 14,15A2,2 0 0,0 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17Z",Lt="M12 2C7.04 2 3 6.04 3 11C3 14.91 5.5 18.24 9 19.47V22H11V19.94C11.33 20 11.66 20 12 20S12.67 20 13 19.94V22H15V19.47C18.5 18.23 21 14.9 21 11C21 6.04 16.96 2 12 2M14.25 14L11.25 17L9.75 15.5L11 14.25L9.75 13L12.75 10L14.25 11.5L13 12.75L14.25 14M16 9H8V7H16V9Z",$t="M10,0.2C9,0.2 8.2,1 8.2,2C8.2,3 9,3.8 10,3.8C11,3.8 11.8,3 11.8,2C11.8,1 11,0.2 10,0.2M15.67,1A7.33,7.33 0 0,0 23,8.33V7A6,6 0 0,1 17,1H15.67M18.33,1C18.33,3.58 20.42,5.67 23,5.67V4.33C21.16,4.33 19.67,2.84 19.67,1H18.33M21,1A2,2 0 0,0 23,3V1H21M7.92,4.03C7.75,4.03 7.58,4.06 7.42,4.11L2,5.8V11H3.8V7.33L5.91,6.67L2,22H3.8L6.67,13.89L9,17V22H10.8V15.59L8.31,11.05L9.04,8.18L10.12,10H15V8.2H11.38L9.38,4.87C9.08,4.37 8.54,4.03 7.92,4.03Z",zt="M18.73,18C15.4,21.69 9.71,22 6,18.64C2.33,15.31 2.04,9.62 5.37,5.93C6.9,4.25 9,3.2 11.27,3C7.96,6.7 8.27,12.39 12,15.71C13.63,17.19 15.78,18 18,18C18.25,18 18.5,18 18.73,18Z",Ot="M17 13V7H19V13H17M17 17V15H19V17H17M13 13V5C13 3.3 11.7 2 10 2S7 3.3 7 5V13C4.8 14.7 4.3 17.8 6 20S10.8 22.7 13 21 15.7 16.2 14 14C13.7 13.6 13.4 13.3 13 13M10 4C10.6 4 11 4.4 11 5V8H9V5C9 4.4 9.4 4 10 4Z",Vt="M12,3.25C12,3.25 6,10 6,14C6,17.32 Line truncated */const bt=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends gt{constructor(t){if(super(t),t.type!==ft||"class"!==t.name||t.strings?.length>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return" "+Object.keys(t).filter((e=>t[e])).join(" ")+" "}update(t,[e]){if(void 0===this.st){this.st=new Set,void 0!==t.strings&&(this.nt=new Set(t.strings.join(" ").split(/\s/).filter((t=>""!==t))));for(const t in e)e[t]&&!this.nt?.has(t)&&this.st.add(t);return this.render(e)}const i=t.element.classList;for(const t of this.st)t in e||(i.remove(t),this.st.delete(t));for(const t in e){const o=!!e[t];o===this.st.has(t)||this.nt?.has(t)||(o?(i.add(t),this.st.add(t)):(i.remove(t),this.st.delete(t)))}return U}});var vt="M6.59,0.66C8.93,-1.15 11.47,1.06 12.04,4.5C12.47,4.5 12.89,4.62 13.27,4.84C13.79,4.24 14.25,3.42 14.07,2.5C13.65,0.35 16.06,-1.39 18.35,1.58C20.16,3.92 17.95,6.46 14.5,7.03C14.5,7.46 14.39,7.89 14.16,8.27C14.76,8.78 15.58,9.24 16.5,9.06C18.63,8.64 20.38,11.04 17.41,13.34C15.07,15.15 12.53,12.94 11.96,9.5C11.53,9.5 11.11,9.37 10.74,9.15C10.22,9.75 9.75,10.58 9.93,11.5C10.35,13.64 7.94,15.39 5.65,12.42C3.83,10.07 6.05,7.53 9.5,6.97C9.5,6.54 9.63,6.12 9.85,5.74C9.25,5.23 8.43,4.76 7.5,4.94C5.37,5.36 3.62,2.96 6.59,0.66M5,16H7A2,2 0 0,1 9,18V24H7V22H5V24H3V18A2,2 0 0,1 5,16M5,18V20H7V18H5M12.93,16H15L12.07,24H10L12.93,16M18,16H21V18H18V22H21V24H18A2,2 0 0,1 16,22V18A2,2 0 0,1 18,16Z",yt="M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M11,15H13V17H11V15M11,7H13V13H11V7",wt="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z",xt="M7.41,15.41L12,10.83L16.59,15.41L18,14L12,8L6,14L7.41,15.41Z",kt="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z",St="M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z",Tt="M12,11A1,1 0 0,0 11,12A1,1 0 0,0 12,13A1,1 0 0,0 13,12A1,1 0 0,0 12,11M12.5,2C17,2 17.11,5.57 14.75,6.75C13.76,7.24 13.32,8.29 13.13,9.22C13.61,9.42 14.03,9.73 14.35,10.13C18.05,8.13 22.03,8.92 22.03,12.5C22.03,17 18.46,17.1 17.28,14.73C16.78,13.74 15.72,13.3 14.79,13.11C14.59,13.59 14.28,14 13.88,14.34C15.87,18.03 15.08,22 11.5,22C7,22 6.91,18.42 9.27,17.24C10.25,16.75 10.69,15.71 10.89,14.79C10.4,14.59 9.97,14.27 9.65,13.87C5.96,15.85 2,15.07 2,11.5C2,7 5.56,6.89 6.74,9.26C7.24,10.25 8.29,10.68 9.22,10.87C9.41,10.39 9.73,9.97 10.14,9.65C8.15,5.96 8.94,2 12.5,2Z",Mt="M5,2V13H8V22L15,10H11L15,2M17,15H19V17H17V15M17,7H19V13H17V7Z",Dt="M8.5 4.5L5.4 9.5L8.5 14.7L5.2 20.5L3.4 19.6L6.1 14.7L3 9.5L6.7 3.6L8.5 4.5M14.7 4.4L11.6 9.5L14.7 14.5L11.4 20.3L9.6 19.4L12.3 14.5L9.2 9.5L12.9 3.5L14.7 4.4M21 4.4L17.9 9.5L21 14.5L17.7 20.3L15.9 19.4L18.6 14.5L15.5 9.5L19.2 3.5L21 4.4",Ct="M12,3L2,12H5V20H19V12H22L12,3M12,8.75A2.25,2.25 0 0,1 14.25,11A2.25,2.25 0 0,1 12,13.25A2.25,2.25 0 0,1 9.75,11A2.25,2.25 0 0,1 12,8.75M12,15C13.5,15 16.5,15.75 16.5,17.25V18H7.5V17.25C7.5,15.75 10.5,15 12,15Z",At="M13 9H11V7H13V9M13 17H11V11H13V17M5 3H19C20.1 3 21 3.89 21 5V19C21 19.53 20.79 20.04 20.41 20.41C20.04 20.79 19.53 21 19 21H5C4.47 21 3.96 20.79 3.59 20.41C3.21 20.04 3 19.53 3 19V5C3 3.89 3.89 3 5 3M19 19V5H5V19H19Z",Pt="M12,17A2,2 0 0,0 14,15C14,13.89 13.1,13 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V10C4,8.89 4.9,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z",Et="M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10A2,2 0 0,1 6,8H15V6A3,3 0 0,0 12,3A3,3 0 0,0 9,6H7A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,17A2,2 0 0,0 14,15A2,2 0 0,0 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17Z",Lt="M12 2C7.04 2 3 6.04 3 11C3 14.91 5.5 18.24 9 19.47V22H11V19.94C11.33 20 11.66 20 12 20S12.67 20 13 19.94V22H15V19.47C18.5 18.23 21 14.9 21 11C21 6.04 16.96 2 12 2M14.25 14L11.25 17L9.75 15.5L11 14.25L9.75 13L12.75 10L14.25 11.5L13 12.75L14.25 14M16 9H8V7H16V9Z",$t="M10,0.2C9,0.2 8.2,1 8.2,2C8.2,3 9,3.8 10,3.8C11,3.8 11.8,3 11.8,2C11.8,1 11,0.2 10,0.2M15.67,1A7.33,7.33 0 0,0 23,8.33V7A6,6 0 0,1 17,1H15.67M18.33,1C18.33,3.58 20.42,5.67 23,5.67V4.33C21.16,4.33 19.67,2.84 19.67,1H18.33M21,1A2,2 0 0,0 23,3V1H21M7.92,4.03C7.75,4.03 7.58,4.06 7.42,4.11L2,5.8V11H3.8V7.33L5.91,6.67L2,22H3.8L6.67,13.89L9,17V22H10.8V15.59L8.31,11.05L9.04,8.18L10.12,10H15V8.2H11.38L9.38,4.87C9.08,4.37 8.54,4.03 7.92,4.03Z",zt="M18.73,18C15.4,21.69 9.71,22 6,18.64C2.33,15.31 2.04,9.62 5.37,5.93C6.9,4.25 9,3.2 11.27,3C7.96,6.7 8.27,12.39 12,15.71C13.63,17.19 15.78,18 18,18C18.25,18 18.5,18 18.73,18Z",Ot="M17 13V7H19V13H17M17 17V15H19V17H17M13 13V5C13 3.3 11.7 2 10 2S7 3.3 7 5V13C4.8 14.7 4.3 17.8 6 20S10.8 22.7 13 21 15.7 16.2 14 14C13.7 13.6 13.4 13.3 13 13M10 4C10.6 4 11 4.4 11 5V8H9V5C9 4.4 9.4 4 10 4Z",Vt="M12,3.25C12,3.25 6,10 6,14C6,17.32 Line truncated
#sortable a:nth-of-type(2n) paper-icon-item { #sortable a:nth-of-type(2n) paper-icon-item {
animation-name: keyframes1; animation-name: keyframes1;
animation-iteration-count: infinite; animation-iteration-count: infinite;
@@ -163,29 +163,29 @@ const ct=t=>(e,i)=>{void 0!==i?i.addInitializer((()=>{customElements.define(t,e)
color: var(--secondary-text-color); color: var(--secondary-text-color);
cursor: pointer; cursor: pointer;
} }
`;const ia=([[t,e],[i,o]],[n,a])=>[t*n+e*a,i*n+o*a],oa=([t,e],[i,o])=>[t+i,e+o],na=t=>t/180*Math.PI,aa=t=>{const{x:e,y:i,r:o,start:n,end:a,rotate:s=0}=t,r=e,l=i,c=o,d=o,h=na(n),u=(na(a)-h)%(2*Math.PI),m=na(s),p=(t=>[[Math.cos(t),-Math.sin(t)],[Math.sin(t),Math.cos(t)]])(m),[_,g]=oa(ia(p,[c*Math.cos(h),d*Math.sin(h)]),[r,l]),[f,b]=oa(ia(p,[c*Math.cos(h+u),d*Math.sin(h+u)]),[r,l]),v=u>Math.PI?1:0,y=u>0?1:0;return["M",_,g,"A",c,d,m/(2*Math.PI)*360,v,y,f,b].join(" ")};function sa(){return sa=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var o in i)Object.prototype.hasOwnProperty.call(i,o)&&(t[o]=i[o])}return t},sa.apply(this,arguments)}function ra(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}function la(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}var ca;ca="function"!=typeof Object.assign?function(t){if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var e=Object(t),i=1;i<arguments.length;i++){var o=arguments[i];if(null!=o)for(var n in o)o.hasOwnProperty(n)&&(e[n]=o[n])}return e}:Object.assign;var da,ha=ca,ua=["","webkit","Moz","MS","ms","o"],ma="undefined"==typeof document?{style:{}}:document.createElement("div"),pa=Math.round,_a=Math.abs,ga=Date.now;function fa(t,e){for(var i,o,n=e[0].toUpperCase()+e.slice(1),a=0;a<ua.length;){if((o=(i=ua[a])?i+n:e)in t)return o;a++}}da="undefined"==typeof window?{}:window;var ba=fa(ma.style,"touchAction"),va=void 0!==ba;var ya="compute",wa="auto",xa="manipulation",ka="none",Ta="pan-x",Sa="pan-y",Ma=function(){if(!va)return!1;var t={},e=da.CSS&&da.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach((function(i){return t[i]=!e||da.CSS.supports("touch-action",i)})),t}(),Da="ontouchstart"in da,Ca=void 0!==fa(da,"PointerEvent"),Aa=Da&&/mobile|tablet|ip(ad|hone|od)|android/i.test(navigator.userAgent),Pa="touch",Ea="mouse",La=25,$a=1,za=4,Oa=8,Va=1,Ha=2,Ra=4,Ia=8,Na=16,Fa=Ha|Ra,Wa=Ia|Na,Ba=Fa|Wa,ja=["x","y"],Ua=["clientX","clientY"];function Ya(t,e,i){var o;if(t)if(t.forEach)t.forEach(e,i);else if(void 0!==t.length)for(o=0;o<t.length;)e.call(i,t[o],o,t),o++;else for(o in t)t.hasOwnProperty(o)&&e.call(i,t[o],o,t)}function qa(t,e){return"function"==typeof t?t.apply(e&&e[0]||void 0,e):t}function Za(t,e){return t.indexOf(e)>-1}var Xa=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===ya&&(t=this.compute()),va&&this.manager.element.style&&Ma[t]&&(this.manager.element.style[ba]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return Ya(this.manager.recognizers,(function(e){qa(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(Za(t,ka))return ka;var e=Za(t,Ta),i=Za(t,Sa);return e&&i?ka:e||i?e?Ta:Sa:Za(t,xa)?xa:wa}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var o=this.actions,n=Za(o,ka)&&!Ma[ka],a=Za(o,Sa)&&!Ma[Sa],s=Za(o,Ta)&&!Ma[Ta];if(n){var r=1===t.pointers.length,l=t.distance<2,c=t.deltaTime<250;if(r&&l&&c)return}if(!s||!a)return n||a&&i&Fa||s&&i&Wa?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function Ka(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function Ga(t){var e=t.length;if(1===e)return{x:pa(t[0].clientX),y:pa(t[0].clientY)};for(var i=0,o=0,n=0;n<e;)i+=t[n].clientX,o+=t[n].clientY,n++;return{x:pa(i/e),y:pa(o/e)}}function Qa(t){for(var e=[],i=0;i<t.pointers.length;)e[i]={clientX:pa(t.pointers[i].clientX),clientY:pa(t.pointers[i].clientY)},i++;return{timeStamp:ga(),pointers:e,center:Ga(e),deltaX:t.deltaX,deltaY:t.deltaY}}function Ja(t,e,i){i||(i=ja);var o=e[i[0]]-t[i[0]],n=e[i[1]]-t[i[1]];return Math.sqrt(o*o+n*n)}function ts(t,e,i){i||(i=ja);var o=e[i[0]]-t[i[0]],n=e[i[1]]-t[i[1]];return 180*Math.atan2(n,o)/Math.PI}function es(t,e){return t===e?Va:_a(t)>=_a(e)?t<0?Ha:Ra:e<0?Ia:Na}function is(t,e,i){return{x:e/t||0,y:i/t||0}}function os(t,e){var i=t.session,o=e.pointers,n=o.length;i.firstInput||(i.firstInput=Qa(e)),n>1&&!i.firstMultiple?i.firstMultiple=Qa(e):1===n&&(i.firstMultiple=!1);var a=i.firstInput,s=i.firstMultiple,r=s?s.center:a.center,l=e.center=Ga(o);e.timeStamp=ga(),e.deltaTime=e.timeStamp-a.timeStamp,e.angle=ts(r,l),e.distance=Ja(r,l),function(t,e){var i=e.center,o=t.offsetDelta||{},n=t.prevDelta||{},a=t.prevInput||{};e.eventType!==$a&&a.eventType!==za||(n=t.prevDelta={x:a.deltaX||0,y:a.deltaY||0},o=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=n.x+(i.x-o.x),e.deltaY=n.y+(i.y-o.y)}(i,e),e.offsetDirection=es(e.deltaX,e.deltaY);var c,d,h=is(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=h.x,e.overallVelocityY=h.y,e.overallVelocity=_a(h.x)>_a(h.y)?h.x:h.y,e.scale=s?(c=s.pointers,Ja((d=o)[0],d[1],Ua)/Ja(c[0],c[1],Ua)):1,e.rotation=s?functio Line truncated `;const en=([[t,e],[i,o]],[a,n])=>[t*a+e*n,i*a+o*n],on=([t,e],[i,o])=>[t+i,e+o],an=t=>t/180*Math.PI,nn=t=>{const{x:e,y:i,r:o,start:a,end:n,rotate:s=0}=t,r=e,l=i,c=o,d=o,h=an(a),u=(an(n)-h)%(2*Math.PI),p=an(s),m=(t=>[[Math.cos(t),-Math.sin(t)],[Math.sin(t),Math.cos(t)]])(p),[_,f]=on(en(m,[c*Math.cos(h),d*Math.sin(h)]),[r,l]),[g,b]=on(en(m,[c*Math.cos(h+u),d*Math.sin(h+u)]),[r,l]),v=u>Math.PI?1:0,y=u>0?1:0;return["M",_,f,"A",c,d,p/(2*Math.PI)*360,v,y,g,b].join(" ")};function sn(){return sn=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var o in i)Object.prototype.hasOwnProperty.call(i,o)&&(t[o]=i[o])}return t},sn.apply(this,arguments)}function rn(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}function ln(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}var cn;cn="function"!=typeof Object.assign?function(t){if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var e=Object(t),i=1;i<arguments.length;i++){var o=arguments[i];if(null!=o)for(var a in o)o.hasOwnProperty(a)&&(e[a]=o[a])}return e}:Object.assign;var dn,hn=cn,un=["","webkit","Moz","MS","ms","o"],pn="undefined"==typeof document?{style:{}}:document.createElement("div"),mn=Math.round,_n=Math.abs,fn=Date.now;function gn(t,e){for(var i,o,a=e[0].toUpperCase()+e.slice(1),n=0;n<un.length;){if((o=(i=un[n])?i+a:e)in t)return o;n++}}dn="undefined"==typeof window?{}:window;var bn=gn(pn.style,"touchAction"),vn=void 0!==bn;var yn="compute",wn="auto",xn="manipulation",kn="none",Sn="pan-x",Tn="pan-y",Mn=function(){if(!vn)return!1;var t={},e=dn.CSS&&dn.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach((function(i){return t[i]=!e||dn.CSS.supports("touch-action",i)})),t}(),Dn="ontouchstart"in dn,Cn=void 0!==gn(dn,"PointerEvent"),An=Dn&&/mobile|tablet|ip(ad|hone|od)|android/i.test(navigator.userAgent),Pn="touch",En="mouse",Ln=25,$n=1,zn=4,On=8,Vn=1,Hn=2,In=4,Rn=8,Fn=16,Nn=Hn|In,jn=Rn|Fn,Wn=Nn|jn,Bn=["x","y"],Un=["clientX","clientY"];function Yn(t,e,i){var o;if(t)if(t.forEach)t.forEach(e,i);else if(void 0!==t.length)for(o=0;o<t.length;)e.call(i,t[o],o,t),o++;else for(o in t)t.hasOwnProperty(o)&&e.call(i,t[o],o,t)}function qn(t,e){return"function"==typeof t?t.apply(e&&e[0]||void 0,e):t}function Zn(t,e){return t.indexOf(e)>-1}var Xn=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===yn&&(t=this.compute()),vn&&this.manager.element.style&&Mn[t]&&(this.manager.element.style[bn]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return Yn(this.manager.recognizers,(function(e){qn(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(Zn(t,kn))return kn;var e=Zn(t,Sn),i=Zn(t,Tn);return e&&i?kn:e||i?e?Sn:Tn:Zn(t,xn)?xn:wn}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var o=this.actions,a=Zn(o,kn)&&!Mn[kn],n=Zn(o,Tn)&&!Mn[Tn],s=Zn(o,Sn)&&!Mn[Sn];if(a){var r=1===t.pointers.length,l=t.distance<2,c=t.deltaTime<250;if(r&&l&&c)return}if(!s||!n)return a||n&&i&Nn||s&&i&jn?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function Kn(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function Gn(t){var e=t.length;if(1===e)return{x:mn(t[0].clientX),y:mn(t[0].clientY)};for(var i=0,o=0,a=0;a<e;)i+=t[a].clientX,o+=t[a].clientY,a++;return{x:mn(i/e),y:mn(o/e)}}function Qn(t){for(var e=[],i=0;i<t.pointers.length;)e[i]={clientX:mn(t.pointers[i].clientX),clientY:mn(t.pointers[i].clientY)},i++;return{timeStamp:fn(),pointers:e,center:Gn(e),deltaX:t.deltaX,deltaY:t.deltaY}}function Jn(t,e,i){i||(i=Bn);var o=e[i[0]]-t[i[0]],a=e[i[1]]-t[i[1]];return Math.sqrt(o*o+a*a)}function ts(t,e,i){i||(i=Bn);var o=e[i[0]]-t[i[0]],a=e[i[1]]-t[i[1]];return 180*Math.atan2(a,o)/Math.PI}function es(t,e){return t===e?Vn:_n(t)>=_n(e)?t<0?Hn:In:e<0?Rn:Fn}function is(t,e,i){return{x:e/t||0,y:i/t||0}}function os(t,e){var i=t.session,o=e.pointers,a=o.length;i.firstInput||(i.firstInput=Qn(e)),a>1&&!i.firstMultiple?i.firstMultiple=Qn(e):1===a&&(i.firstMultiple=!1);var n=i.firstInput,s=i.firstMultiple,r=s?s.center:n.center,l=e.center=Gn(o);e.timeStamp=fn(),e.deltaTime=e.timeStamp-n.timeStamp,e.angle=ts(r,l),e.distance=Jn(r,l),function(t,e){var i=e.center,o=t.offsetDelta||{},a=t.prevDelta||{},n=t.prevInput||{};e.eventType!==$n&&n.eventType!==zn||(a=t.prevDelta={x:n.deltaX||0,y:n.deltaY||0},o=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=a.x+(i.x-o.x),e.deltaY=a.y+(i.y-o.y)}(i,e),e.offsetDirection=es(e.deltaX,e.deltaY);var c,d,h=is(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=h.x,e.overallVelocityY=h.y,e.overallVelocity=_n(h.x)>_n(h.y)?h.x:h.y,e.scale=s?(c=s.pointers,Jn((d=o)[0],d[1],Un)/Jn(c[0],c[1],Un)):1,e.rotation=s?functio Line truncated
/** /**
* @license * @license
* Copyright 2018 Google LLC * Copyright 2018 Google LLC
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","PageUp","PageDown","Home","End"]);let or=class extends rt{constructor(){super(...arguments),this.disabled=!1,this.step=1,this.min=0,this.max=100,this._localValue=this.value,this._localLow=this.low,this._localHigh=this.high,this._getPercentageFromEvent=t=>{const e=this._slider.getBoundingClientRect(),i=2*(t.center.x-e.left-e.width/2)/e.width,o=2*(t.center.y-e.top-e.height/2)/e.height,[,n]=function(t,e){return[Math.sqrt(t*t+e*e),Math.atan2(e,t)]}(i,o),a=(n/(2*Math.PI)*360+45-135+360)%360-45;return Math.max(Math.min(a/er,1),0)}}_valueToPercentage(t){return(Sn(t,this.min,this.max)-this.min)/(this.max-this.min)}_percentageToValue(t){return(this.max-this.min)*t+this.min}_steppedValue(t){return Math.round(t/this.step)*this.step}_boundedValue(t){var e,i;const o="high"===this._activeSlider?Math.min(null!==(e=this._localLow)&&void 0!==e?e:this.max):this.min,n="low"===this._activeSlider?Math.max(null!==(i=this._localHigh)&&void 0!==i?i:this.min):this.max;return Math.min(Math.max(t,o),n)}firstUpdated(t){super.firstUpdated(t),this._setupListeners()}updated(t){super.updated(t),this._activeSlider||(t.has("value")&&(this._localValue=this.value),t.has("low")&&(this._localLow=this.low),t.has("high")&&(this._localHigh=this.high))}connectedCallback(){super.connectedCallback(),this._setupListeners()}disconnectedCallback(){super.disconnectedCallback()}_findActiveSlider(t){var e,i;if(!this.dual)return"value";const o=Math.max(null!==(e=this._localLow)&&void 0!==e?e:this.min,this.min),n=Math.min(null!==(i=this._localHigh)&&void 0!==i?i:this.max,this.max);if(o>=t)return"low";if(n<=t)return"high";return Math.abs(t-o)<=Math.abs(t-n)?"low":"high"}_setActiveValue(t){switch(this._activeSlider){case"high":this._localHigh=t;break;case"low":this._localLow=t;break;case"value":this._localValue=t}}_getActiveValue(){switch(this._activeSlider){case"high":return this._localHigh;case"low":return this._localLow;case"value":return this._localValue}}_setupListeners(){this._interaction&&!this._mc&&(this._mc=new Us(this._interaction,{inputClass:Ds}),this._mc.add(new Hs({direction:Ba,enable:!0,threshold:0})),this._mc.add(new zs({event:"singletap"})),this._mc.on("pan",(t=>{t.srcEvent.stopPropagation(),t.srcEvent.preventDefault()})),this._mc.on("panstart",(t=>{var e,i;if(this.disabled)return;const o=this._getPercentageFromEvent(t),n=this._percentageToValue(o);this._activeSlider=this._findActiveSlider(n),this._lastSlider=this._activeSlider,null===(i=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("#slider"))||void 0===i||i.focus()})),this._mc.on("pancancel",(()=>{this.disabled||(this._activeSlider=void 0)})),this._mc.on("panmove",(t=>{if(this.disabled)return;const e=this._getPercentageFromEvent(t),i=this._percentageToValue(e),o=this._boundedValue(i);this._setActiveValue(o);const n=this._steppedValue(o);this._activeSlider&&Tn(this,`${this._activeSlider}-changing`,{value:n})})),this._mc.on("panend",(t=>{if(this.disabled)return;const e=this._getPercentageFromEvent(t),i=this._percentageToValue(e),o=this._boundedValue(i),n=this._steppedValue(o);this._setActiveValue(n),this._activeSlider&&(Tn(this,`${this._activeSlider}-changing`,{value:void 0}),Tn(this,`${this._activeSlider}-changed`,{value:n})),this._activeSlider=void 0})),this._mc.on("singletap",(t=>{var e,i;if(this.disabled)return;const o=this._getPercentageFromEvent(t),n=this._percentageToValue(o);this._activeSlider=this._findActiveSlider(n);const a=this._boundedValue(n),s=this._steppedValue(a);this._setActiveValue(s),this._activeSlider&&(Tn(this,`${this._activeSlider}-changing`,{value:void 0}),Tn(this,`${this._activeSlider}-changed`,{value:s})),this._lastSlider=this._activeSlider,null===(i=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("#slider"))||void 0===i||i.focus(),this._activeSlider=void 0})))}get _tenPercentStep(){return Math.max(this.step,(this.max-this.min)/10)}_handleKeyDown(t){var e,i,o;if(!ir.has(t.code))return;t.preventDefault(),this._lastSlider&&(null===(i=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById(this._lastSlider))||void 0===i||i.focus()),this._activeSlider=null!==(o=this._lastSlider)&&void 0!==o?o:t.currentTarget.id,this._lastSlider=void 0;const n=this._getActiveValue();switch(t.code){case"ArrowRight":case"ArrowUp":this._setActiveValue(this._boundedValue((null!=n?n:this.min)+this.step));break;case"ArrowLeft":case"ArrowDown":this._setActiveValue(this._boundedValue((null!=n?n:this.min)-this.step));break;case"PageUp":this._setActiveValue(this._steppedValue(this._boundedValue((null!=n?n:this.min)+this._tenPercentStep)));break;case"PageDown":this._setActiveValue(this._steppedValue(this._boundedValue((null!=n?n:this.min)-this._tenPercentStep)));break;case"Home":this._setActiveValue(this._boundedValue(this.min));break;case"End":this._setActiveValue(this._boundedValue(this.max))}Tn(this,`${this._activeSlider}-changing`,{value:this._getActiveValue()}),this._activeSliderLine truncated const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","PageUp","PageDown","Home","End"]);let or=class extends lt{constructor(){super(...arguments),this.disabled=!1,this.step=1,this.min=0,this.max=100,this._localValue=this.value,this._localLow=this.low,this._localHigh=this.high,this._getPercentageFromEvent=t=>{const e=this._slider.getBoundingClientRect(),i=2*(t.center.x-e.left-e.width/2)/e.width,o=2*(t.center.y-e.top-e.height/2)/e.height,[,a]=function(t,e){return[Math.sqrt(t*t+e*e),Math.atan2(e,t)]}(i,o),n=(a/(2*Math.PI)*360+45-135+360)%360-45;return Math.max(Math.min(n/er,1),0)}}_valueToPercentage(t){return(Sa(t,this.min,this.max)-this.min)/(this.max-this.min)}_percentageToValue(t){return(this.max-this.min)*t+this.min}_steppedValue(t){return Math.round(t/this.step)*this.step}_boundedValue(t){var e,i;const o="high"===this._activeSlider?Math.min(null!==(e=this._localLow)&&void 0!==e?e:this.max):this.min,a="low"===this._activeSlider?Math.max(null!==(i=this._localHigh)&&void 0!==i?i:this.min):this.max;return Math.min(Math.max(t,o),a)}firstUpdated(t){super.firstUpdated(t),this._setupListeners()}updated(t){super.updated(t),this._activeSlider||(t.has("value")&&(this._localValue=this.value),t.has("low")&&(this._localLow=this.low),t.has("high")&&(this._localHigh=this.high))}connectedCallback(){super.connectedCallback(),this._setupListeners()}disconnectedCallback(){super.disconnectedCallback()}_findActiveSlider(t){var e,i;if(!this.dual)return"value";const o=Math.max(null!==(e=this._localLow)&&void 0!==e?e:this.min,this.min),a=Math.min(null!==(i=this._localHigh)&&void 0!==i?i:this.max,this.max);if(o>=t)return"low";if(a<=t)return"high";return Math.abs(t-o)<=Math.abs(t-a)?"low":"high"}_setActiveValue(t){switch(this._activeSlider){case"high":this._localHigh=t;break;case"low":this._localLow=t;break;case"value":this._localValue=t}}_getActiveValue(){switch(this._activeSlider){case"high":return this._localHigh;case"low":return this._localLow;case"value":return this._localValue}}_setupListeners(){this._interaction&&!this._mc&&(this._mc=new Us(this._interaction,{inputClass:Ds}),this._mc.add(new Hs({direction:Wn,enable:!0,threshold:0})),this._mc.add(new zs({event:"singletap"})),this._mc.on("pan",(t=>{t.srcEvent.stopPropagation(),t.srcEvent.preventDefault()})),this._mc.on("panstart",(t=>{var e,i;if(this.disabled)return;const o=this._getPercentageFromEvent(t),a=this._percentageToValue(o);this._activeSlider=this._findActiveSlider(a),this._lastSlider=this._activeSlider,null===(i=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("#slider"))||void 0===i||i.focus()})),this._mc.on("pancancel",(()=>{this.disabled||(this._activeSlider=void 0)})),this._mc.on("panmove",(t=>{if(this.disabled)return;const e=this._getPercentageFromEvent(t),i=this._percentageToValue(e),o=this._boundedValue(i);this._setActiveValue(o);const a=this._steppedValue(o);this._activeSlider&&ka(this,`${this._activeSlider}-changing`,{value:a})})),this._mc.on("panend",(t=>{if(this.disabled)return;const e=this._getPercentageFromEvent(t),i=this._percentageToValue(e),o=this._boundedValue(i),a=this._steppedValue(o);this._setActiveValue(a),this._activeSlider&&(ka(this,`${this._activeSlider}-changing`,{value:void 0}),ka(this,`${this._activeSlider}-changed`,{value:a})),this._activeSlider=void 0})),this._mc.on("singletap",(t=>{var e,i;if(this.disabled)return;const o=this._getPercentageFromEvent(t),a=this._percentageToValue(o);this._activeSlider=this._findActiveSlider(a);const n=this._boundedValue(a),s=this._steppedValue(n);this._setActiveValue(s),this._activeSlider&&(ka(this,`${this._activeSlider}-changing`,{value:void 0}),ka(this,`${this._activeSlider}-changed`,{value:s})),this._lastSlider=this._activeSlider,null===(i=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("#slider"))||void 0===i||i.focus(),this._activeSlider=void 0})))}get _tenPercentStep(){return Math.max(this.step,(this.max-this.min)/10)}_handleKeyDown(t){var e,i,o;if(!ir.has(t.code))return;t.preventDefault(),this._lastSlider&&(null===(i=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById(this._lastSlider))||void 0===i||i.focus()),this._activeSlider=null!==(o=this._lastSlider)&&void 0!==o?o:t.currentTarget.id,this._lastSlider=void 0;const a=this._getActiveValue();switch(t.code){case"ArrowRight":case"ArrowUp":this._setActiveValue(this._boundedValue((null!=a?a:this.min)+this.step));break;case"ArrowLeft":case"ArrowDown":this._setActiveValue(this._boundedValue((null!=a?a:this.min)-this.step));break;case"PageUp":this._setActiveValue(this._steppedValue(this._boundedValue((null!=a?a:this.min)+this._tenPercentStep)));break;case"PageDown":this._setActiveValue(this._steppedValue(this._boundedValue((null!=a?a:this.min)-this._tenPercentStep)));break;case"Home":this._setActiveValue(this._boundedValue(this.min));break;case"End":this._setActiveValue(this._boundedValue(this.max))}ka(this,`${this._activeSlider}-changing`,{value:this._getActiveValue()}),this._activeSliderLine truncated
<g class=${bt({inactive:Boolean(this.inactive)})}> <g class=${bt({inactive:Boolean(this.inactive)})}>
<path <path
class="arc arc-clear" class="arc arc-clear"
d=${a} d=${n}
stroke-dasharray=${h[0]} stroke-dasharray=${h[0]}
stroke-dashoffset=${h[1]} stroke-dashoffset=${h[1]}
/> />
<path <path
class="arc arc-colored ${bt({[t]:!0})}" class="arc arc-colored ${bt({[t]:!0})}"
d=${a} d=${n}
stroke-dasharray=${h[0]} stroke-dasharray=${h[0]}
stroke-dashoffset=${h[1]} stroke-dashoffset=${h[1]}
/> />
<path <path
.id=${t} .id=${t}
d=${a} d=${n}
class="arc arc-active ${bt({[t]:!0})}" class="arc arc-active ${bt({[t]:!0})}"
stroke-dasharray=${d[0]} stroke-dasharray=${d[0]}
stroke-dashoffset=${d[1]} stroke-dashoffset=${d[1]}
@@ -195,32 +195,32 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
aria-valuemax=${this.max} aria-valuemax=${this.max}
aria-valuenow=${null!=this._localValue?this._steppedValue(this._localValue):void 0} aria-valuenow=${null!=this._localValue?this._steppedValue(this._localValue):void 0}
aria-disabled=${this.disabled} aria-disabled=${this.disabled}
aria-label=${(t=>t??Y)(null!==(n=this.lowLabel)&&void 0!==n?n:this.label)} aria-label=${(t=>t??Y)(null!==(a=this.lowLabel)&&void 0!==a?a:this.label)}
@keydown=${this._handleKeyDown} @keydown=${this._handleKeyDown}
@keyup=${this._handleKeyUp} @keyup=${this._handleKeyUp}
/> />
${m?j` ${p?B`
<path <path
class="current arc-current" class="current arc-current"
d=${a} d=${n}
stroke-dasharray=${m[0]} stroke-dasharray=${p[0]}
stroke-dashoffset=${m[1]} stroke-dashoffset=${p[1]}
/> />
`:Y} `:Y}
<path <path
class="target-border ${bt({[t]:!0})}" class="target-border ${bt({[t]:!0})}"
d=${a} d=${n}
stroke-dasharray=${u[0]} stroke-dasharray=${u[0]}
stroke-dashoffset=${u[1]} stroke-dashoffset=${u[1]}
/> />
<path <path
class="target" class="target"
d=${a} d=${n}
stroke-dasharray=${u[0]} stroke-dasharray=${u[0]}
stroke-dashoffset=${u[1]} stroke-dashoffset=${u[1]}
/> />
</g> </g>
`}render(){const t=aa({x:0,y:0,start:0,end:er,r:145}),e=this.dual?this._localLow:this._localValue,i=this._localHigh,o=this.current,n=o?this._strokeCircleDashArc(o):void 0;return B` `}render(){const t=nn({x:0,y:0,start:0,end:er,r:145}),e=this.dual?this._localLow:this._localValue,i=this._localHigh,o=this.current,a=o?this._strokeCircleDashArc(o):void 0;return W`
<svg <svg
id="slider" id="slider"
viewBox="0 0 320 320" viewBox="0 0 320 320"
@@ -238,12 +238,12 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
</g> </g>
<g id="display"> <g id="display">
<path class="background" d=${t} /> <path class="background" d=${t} />
${n?j` ${a?B`
<path <path
class="current" class="current"
d=${t} d=${t}
stroke-dasharray=${n[0]} stroke-dasharray=${a[0]}
stroke-dashoffset=${n[1]} stroke-dashoffset=${a[1]}
/> />
`:Y} `:Y}
${null!=e?this.renderArc(this.dual?"low":"value",e,!this.dual&&this.mode||"start"):Y} ${null!=e?this.renderArc(this.dual?"low":"value",e,!this.dual&&this.mode||"start"):Y}
@@ -403,9 +403,9 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
.high { .high {
stroke: var(--state-climate-cool-color); stroke: var(--state-climate-cool-color);
} }
`}};function nr(t){var e,i;return B` `}};function ar(t){var e,i;return W`
<ha-card class="gunmalmg-card ${t.hvacMode} ${t._isLocked?"locked":""}"> <ha-card class="gunmalmg-card ${t.hvacMode} ${t._isLocked?"locked":""}">
${t._showClassicPopup?function(t){var e,i,o;return B` ${t._showClassicPopup?function(t){var e,i,o;return W`
<div class="classic-popup-backdrop" @click=${()=>t._closeClassicPopup()}></div> <div class="classic-popup-backdrop" @click=${()=>t._closeClassicPopup()}></div>
<div class="classic-popup-container"> <div class="classic-popup-container">
<ha-icon-button <ha-icon-button
@@ -414,11 +414,11 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
@click=${()=>t._closeClassicPopup()} @click=${()=>t._closeClassicPopup()}
tabindex="0" tabindex="0"
></ha-icon-button> ></ha-icon-button>
${(null===(e=t._config)||void 0===e?void 0:e.disable_menu)?"":B` ${(null===(e=t._config)||void 0===e?void 0:e.disable_menu)?"":W`
<ha-icon-button <ha-icon-button
class="classic-popup-more-info" class="classic-popup-more-info"
.label=${t.hass.localize("ui.panel.lovelace.cards.show_more_info")} .label=${t.hass.localize("ui.panel.lovelace.cards.show_more_info")}
.path=${Tt} .path=${St}
@click=${()=>{t._closeClassicPopup(),t._handleMoreInfo()}} @click=${()=>{t._closeClassicPopup(),t._handleMoreInfo()}}
tabindex="0" tabindex="0"
></ha-icon-button> ></ha-icon-button>
@@ -438,10 +438,10 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
</div> </div>
<div class="gunmalmg-center" @click=${()=>t._openClassicPopup()}> <div class="gunmalmg-center" @click=${()=>t._openClassicPopup()}>
<div class="temps"> <div class="temps">
${(()=>{var e,i,o,n;const a=(null===(e=t.hass)||void 0===e?void 0:e.locale)||void 0,s=new Intl.NumberFormat(a,{minimumFractionDigits:1,maximumFractionDigits:1}),r=t._display_top,l=t._display_bottom,c=(null===(n=null===(o=null===(i=t.hass)||void 0===i?void 0:i.config)||void 0===o?void 0:o.unit_system)||void 0===n?void 0:n.temperature)||"",d=null==r?t.hass?t.hass.localize("extra_states.temp_unavailable"):"":s.format(r),h=null==l?null:s.format(l);return B` ${(()=>{var e,i,o,a;const n=(null===(e=t.hass)||void 0===e?void 0:e.locale)||void 0,s=new Intl.NumberFormat(n,{minimumFractionDigits:1,maximumFractionDigits:1}),r=t._display_top,l=t._display_bottom,c=(null===(a=null===(o=null===(i=t.hass)||void 0===i?void 0:i.config)||void 0===o?void 0:o.unit_system)||void 0===a?void 0:a.temperature)||"",d=null==r?t.hass?t.hass.localize("extra_states.temp_unavailable"):"":s.format(r),h=null==l?null:s.format(l);return W`
<div class="gunmalmg-temps-inline"> <div class="gunmalmg-temps-inline">
<span class="gunmalmg-temp-main ${t._hasError?"has-error":""}">${d}<span class="gunmalmg-uom"> ${c}</span></span> <span class="gunmalmg-temp-main ${t._hasError?"has-error":""}">${d}<span class="gunmalmg-uom"> ${c}</span></span>
${h?B`<span class="gunmalmg-temp-secondary">(${h}<span class="gunmalmg-uom"> ${c}</span>)</span>`:""} ${h?W`<span class="gunmalmg-temp-secondary">(${h}<span class="gunmalmg-uom"> ${c}</span>)</span>`:""}
</div> </div>
`})()} `})()}
</div> </div>
@@ -449,11 +449,11 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
<div class="gunmalmg-right"> <div class="gunmalmg-right">
<div class="gunmalmg-presets-scroll"> <div class="gunmalmg-presets-scroll">
<div id="presets" class="gunmalmg-presets"> <div id="presets" class="gunmalmg-presets">
${(null===(e=t._config)||void 0===e?void 0:e.disable_presets)?"":t.presets.map((e=>B`${t._renderPreset(e,t.preset)}`))} ${(null===(e=t._config)||void 0===e?void 0:e.disable_presets)?"":t.presets.map((e=>W`${t._renderPreset(e,t.preset)}`))}
</div> </div>
</div> </div>
<div class="gunmalmg-actions"> <div class="gunmalmg-actions">
${(null===(i=t._config)||void 0===i?void 0:i.allow_lock_toggle)?B` ${(null===(i=t._config)||void 0===i?void 0:i.allow_lock_toggle)?W`
<ha-icon-button <ha-icon-button
class="gunmalmg-lock-btn ${t._isLocked?"locked":"unlocked"}" class="gunmalmg-lock-btn ${t._isLocked?"locked":"unlocked"}"
.path=${t._isLocked?Pt:Et} .path=${t._isLocked?Pt:Et}
@@ -461,38 +461,38 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
tabindex="0" tabindex="0"
></ha-icon-button> ></ha-icon-button>
`:""} `:""}
${function(t){var e,i,o,n;return(null===(e=t._config)||void 0===e?void 0:e.disable_timed_preset)?B``:B` ${function(t){var e,i,o,a;return(null===(e=t._config)||void 0===e?void 0:e.disable_timed_preset)?W``:W`
<div class="gunmalmg-timed-preset"> <div class="gunmalmg-timed-preset">
${t.timedPresetActive?B` ${t.timedPresetActive?W`
<span class="gunmalmg-timed-remaining" <span class="gunmalmg-timed-remaining"
title="${_n({hass:t.hass,string:"extra_states.cancel_timed_preset"})}" title="${ma({hass:t.hass,string:"extra_states.cancel_timed_preset"})}"
@click=${t._handleCancelTimedPreset}> @click=${t._handleCancelTimedPreset}>
${t._formatRemainingTime(t.timedPresetRemainingTime)} ${t._formatRemainingTime(t.timedPresetRemainingTime)}
</span> </span>
${(null!==(i=t.timedPresetRemainingTime)&&void 0!==i?i:0)<60?B` ${(null!==(i=t.timedPresetRemainingTime)&&void 0!==i?i:0)<60?W`
<span class="gunmalmg-timed-label">${_n({hass:t.hass,string:"extra_states.minutes"})}</span> <span class="gunmalmg-timed-label">${ma({hass:t.hass,string:"extra_states.minutes"})}</span>
`:""} `:""}
`:(null===(o=t._config)||void 0===o?void 0:o.use_manual_duration_input)?B` `:(null===(o=t._config)||void 0===o?void 0:o.use_manual_duration_input)?W`
<input <input
type="number" type="number"
class="gunmalmg-timed-input ${t.timedPresetDuration?"active":""}" class="gunmalmg-timed-input ${t.timedPresetDuration?"active":""}"
.value=${null!==(n=t.timedPresetDuration)&&void 0!==n?n:""} .value=${null!==(a=t.timedPresetDuration)&&void 0!==a?a:""}
@input=${t._handleTimedPresetDurationChange} @input=${t._handleTimedPresetDurationChange}
placeholder="0" placeholder="0"
min="0" min="0"
max="1440" max="1440"
title="${_n({hass:t.hass,string:"extra_states.timed_preset_title"})}" title="${ma({hass:t.hass,string:"extra_states.timed_preset_title"})}"
/> />
<span class="gunmalmg-timed-label">${_n({hass:t.hass,string:"extra_states.minutes"})}</span> <span class="gunmalmg-timed-label">${ma({hass:t.hass,string:"extra_states.minutes"})}</span>
`:B` `:W`
<select <select
class="gunmalmg-timed-select ${t.timedPresetDuration?"active":""}" class="gunmalmg-timed-select ${t.timedPresetDuration?"active":""}"
@change=${t._handleTimedPresetSelectChange} @change=${t._handleTimedPresetSelectChange}
title="${_n({hass:t.hass,string:"extra_states.timed_preset_title"})}" title="${ma({hass:t.hass,string:"extra_states.timed_preset_title"})}"
> >
<option value="" ?selected=${!t.timedPresetDuration}>--</option> <option value="" ?selected=${!t.timedPresetDuration}>--</option>
<option value="15" ?selected=${15===t.timedPresetDuration}>15 ${_n({hass:t.hass,string:"extra_states.minutes"})}</option> <option value="15" ?selected=${15===t.timedPresetDuration}>15 ${ma({hass:t.hass,string:"extra_states.minutes"})}</option>
<option value="30" ?selected=${30===t.timedPresetDuration}>30 ${_n({hass:t.hass,string:"extra_states.minutes"})}</option> <option value="30" ?selected=${30===t.timedPresetDuration}>30 ${ma({hass:t.hass,string:"extra_states.minutes"})}</option>
<option value="60" ?selected=${60===t.timedPresetDuration}>1 h</option> <option value="60" ?selected=${60===t.timedPresetDuration}>1 h</option>
<option value="120" ?selected=${120===t.timedPresetDuration}>2 h</option> <option value="120" ?selected=${120===t.timedPresetDuration}>2 h</option>
<option value="240" ?selected=${240===t.timedPresetDuration}>4 h</option> <option value="240" ?selected=${240===t.timedPresetDuration}>4 h</option>
@@ -506,7 +506,7 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
</div> </div>
</div> </div>
</ha-card> </ha-card>
`}t([ut({type:Boolean,reflect:!0})],or.prototype,"disabled",void 0),t([ut({type:Boolean})],or.prototype,"dual",void 0),t([ut({type:String})],or.prototype,"mode",void 0),t([ut({type:Boolean})],or.prototype,"inactive",void 0),t([ut({type:String})],or.prototype,"label",void 0),t([ut({type:String,attribute:"low-label"})],or.prototype,"lowLabel",void 0),t([ut({type:String,attribute:"high-label"})],or.prototype,"highLabel",void 0),t([ut({type:Number})],or.prototype,"value",void 0),t([ut({type:Number})],or.prototype,"low",void 0),t([ut({type:Number})],or.prototype,"high",void 0),t([ut({type:Number})],or.prototype,"current",void 0),t([ut({type:Number})],or.prototype,"step",void 0),t([ut({type:Number})],or.prototype,"min",void 0),t([ut({type:Number})],or.prototype,"max",void 0),t([mt()],or.prototype,"_localValue",void 0),t([mt()],or.prototype,"_localLow",void 0),t([mt()],or.prototype,"_localHigh",void 0),t([mt()],or.prototype,"_activeSlider",void 0),t([mt()],or.prototype,"_lastSlider",void 0),t([_t("#slider")],or.prototype,"_slider",void 0),t([_t("#interaction")],or.prototype,"_interaction",void 0),or=t([ct("vt-ha-control-circular-slider")],or);const ar=s` `}t([pt({type:Boolean,reflect:!0})],or.prototype,"disabled",void 0),t([pt({type:Boolean})],or.prototype,"dual",void 0),t([pt({type:String})],or.prototype,"mode",void 0),t([pt({type:Boolean})],or.prototype,"inactive",void 0),t([pt({type:String})],or.prototype,"label",void 0),t([pt({type:String,attribute:"low-label"})],or.prototype,"lowLabel",void 0),t([pt({type:String,attribute:"high-label"})],or.prototype,"highLabel",void 0),t([pt({type:Number})],or.prototype,"value",void 0),t([pt({type:Number})],or.prototype,"low",void 0),t([pt({type:Number})],or.prototype,"high",void 0),t([pt({type:Number})],or.prototype,"current",void 0),t([pt({type:Number})],or.prototype,"step",void 0),t([pt({type:Number})],or.prototype,"min",void 0),t([pt({type:Number})],or.prototype,"max",void 0),t([mt()],or.prototype,"_localValue",void 0),t([mt()],or.prototype,"_localLow",void 0),t([mt()],or.prototype,"_localHigh",void 0),t([mt()],or.prototype,"_activeSlider",void 0),t([mt()],or.prototype,"_lastSlider",void 0),t([_t("#slider")],or.prototype,"_slider",void 0),t([_t("#interaction")],or.prototype,"_interaction",void 0),or=t([dt("vt-ha-control-circular-slider")],or);const nr=s`
:host([theme="gunmalmg"]) vt-ha-control-circular-slider { display: none; } :host([theme="gunmalmg"]) vt-ha-control-circular-slider { display: none; }
:host([theme="gunmalmg"]) vt-ha-control-circular-slider { display: none !important; } :host([theme="gunmalmg"]) vt-ha-control-circular-slider { display: none !important; }
:host([theme="gunmalmg"]) .disabled-circle-container { display: block; background: none; } :host([theme="gunmalmg"]) .disabled-circle-container { display: block; background: none; }
@@ -1216,9 +1216,9 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
color: var(--disabled-text-color); color: var(--disabled-text-color);
pointer-events: none; pointer-events: none;
} }
`;var rr;let lr=rr=class extends rt{constructor(){super(...arguments),this.hass=null,this.entityId="",this.visible=!1,this.targetTemp=null,this.roomTemp=null,this.regulatedTemp=null,this.extTemp=null,this.powerPercent=null,this._history=[],this._loading=!1,this._chart=null,this._canvas=null,this._chartReady=!1,this._destroyed=!1,this._lastEntityId="",this._initialViewSet=!1}connectedCallback(){super.connectedCallback(),this._destroyed=!1}disconnectedCallback(){super.disconnectedCallback(),this._destroyed=!0,this._destroyChart()}async firstUpdated(){var t;await this._initChart(),this._addLiveDataPoint(),this.entityId&&this.hass&&(this._lastEntityId=this.entityId,await this._fetchHistory()),this.visible&&this._chartReady&&(null===(t=this._chart)||void 0===t||t.resize(),this._updateChart(),this._applyInitialView())}updated(t){if(t.has("visible")&&this.visible&&this._chartReady)return void requestAnimationFrame((()=>{var t;null===(t=this._chart)||void 0===t||t.resize(),this._updateChart(),this._applyInitialView()}));if(t.has("entityId")&&this.entityId&&this.entityId!==this._lastEntityId)return this._lastEntityId=this.entityId,this._history=[],void this._fetchHistory().then((()=>{var t;this._chartReady&&this.visible&&(null===(t=this._chart)||void 0===t||t.resize(),this._updateChart(),this._initialViewSet=!1,this._applyInitialView())}));const e=["targetTemp","roomTemp","regulatedTemp","extTemp","powerPercent"].some((e=>t.has(e)));!e||null===this.targetTemp&&null===this.roomTemp&&null===this.powerPercent||(this._addLiveDataPoint(),this._chartReady&&this.visible&&this._updateChart())}async _fetchHistory(){if(!this.hass||!this.entityId)return;this._loading=!0;const t=new Date,e=`history/period/${new Date(t.getTime()-864e5).toISOString()}?filter_entity_id=${this.entityId}&end_time=${t.toISOString()}&significant_changes_only=false&minimal_response=false`;try{const t=await this.hass.callApi("GET",e);if(!Array.isArray(t)||0===t.length)return;const i=t[0].filter((t=>t.attributes&&t.last_updated)).map((t=>{var e,i,o,n,a,s,r,l,c,d,h,u,m,p,_,g,f,b,v,y,w,x,k;return{timestamp:new Date(t.last_updated).getTime(),targetTemp:null!==(e=t.attributes.temperature)&&void 0!==e?e:null,roomTemp:null!==(i=t.attributes.current_temperature)&&void 0!==i?i:null,regulatedTemp:null!==(l=null!==(s=null===(a=null===(n=null===(o=t.attributes)||void 0===o?void 0:o.vtherm_over_climate)||void 0===n?void 0:n.regulation)||void 0===a?void 0:a.regulated_target_temperature)&&void 0!==s?s:null===(r=t.attributes)||void 0===r?void 0:r.regulated_target_temperature)&&void 0!==l?l:null,extTemp:null!==(h=null===(d=null===(c=t.attributes)||void 0===c?void 0:c.specific_states)||void 0===d?void 0:d.ext_current_temperature)&&void 0!==h?h:null,powerPercent:null!==(k=null!==(v=null!==(g=null!==(m=null===(u=t.attributes)||void 0===u?void 0:u.power_percent)&&void 0!==m?m:null===(_=null===(p=t.attributes)||void 0===p?void 0:p.specific_states)||void 0===_?void 0:_.power_percent)&&void 0!==g?g:null===(b=null===(f=t.attributes)||void 0===f?void 0:f.vtherm_over_switch)||void 0===b?void 0:b.power_percent)&&void 0!==v?v:null===(x=null===(w=null===(y=t.attributes)||void 0===y?void 0:y.vtherm_over_climate)||void 0===w?void 0:w.valve_regulation)||void 0===x?void 0:x.power_percent)&&void 0!==k?k:null}})).filter((t=>null!==t.targetTemp||null!==t.roomTemp)),o=i.length>0?i[i.length-1].timestamp:0,n=this._history.filter((t=>t.timestamp>o));this._history=[...i,...n].slice(-rr.MAX_POINTS)}catch(t){console.error("[VtRegulationChart] History fetch failed:",t)}finally{this._loading=!1}}_addLiveDataPoint(){var t,e;const i=Date.now(),o=this._history[this._history.length-1],n={timestamp:i,targetTemp:this.targetTemp,roomTemp:this.roomTemp,regulatedTemp:null!==(t=this.regulatedTemp)&&void 0!==t?t:null,extTemp:null!==(e=this.extTemp)&&void 0!==e?e:null,powerPercent:this.powerPercent};o&&i-o.timestamp<3e4?this._history=[...this._history.slice(0,-1),n]:this._history=[...this._history,n].slice(-rr.MAX_POINTS)}_resolveColor(t,e){return getComputedStyle(this).getPropertyValue(t).trim()||e}async _initChart(){var t,e;if(!this._destroyed&&(this._canvas=null!==(e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("canvas"))&&void 0!==e?e:null,this._canvas))try{const[{Chart:t,registerables:e},{default:i}]=await Promise.all([Promise.resolve().then((function(){return r_})),Promise.resolve().then((function(){return pg}))]);if(await Promise.resolve().then((function(){return Ob})),this._destroyed)return;t.register(...e,i);const o=this._resolveColor("--primary-text-color","#e5e5e5"),n=this._resolveColor("--secondary-text-color","#9e9e9e"),a="rgba(128,128,128,0.18)";this._chart=new t(this._canvas,{type:"line",data:{datasets:[{label:"Consigne",data:[],borderColor:"#f9a21f",backgroundColor:"rgba(249,162,31,0.08)",borderWidth:2,pointRadius:0,pointHoverRadius:4,tension:.3,yAxisID:"yTemp"},{label:"Pièce",data:[],borderColor:"#3a9ff2",backgroundColor:"rgba(58,159,242,0.08)",borderWidth:2,pointRadius:0,po Line truncated `;var rr;let lr=rr=class extends lt{constructor(){super(...arguments),this.hass=null,this.entityId="",this.visible=!1,this.targetTemp=null,this.roomTemp=null,this.regulatedTemp=null,this.extTemp=null,this.powerPercent=null,this._history=[],this._loading=!1,this._chart=null,this._canvas=null,this._chartReady=!1,this._destroyed=!1,this._lastEntityId="",this._initialViewSet=!1}connectedCallback(){super.connectedCallback(),this._destroyed=!1}disconnectedCallback(){super.disconnectedCallback(),this._destroyed=!0,this._destroyChart()}async firstUpdated(){var t;await this._initChart(),this._addLiveDataPoint(),this.entityId&&this.hass&&(this._lastEntityId=this.entityId,await this._fetchHistory()),this.visible&&this._chartReady&&(null===(t=this._chart)||void 0===t||t.resize(),this._updateChart(),this._applyInitialView())}updated(t){if(t.has("visible")&&this.visible&&this._chartReady)return void requestAnimationFrame((()=>{var t;null===(t=this._chart)||void 0===t||t.resize(),this._updateChart(),this._applyInitialView()}));if(t.has("entityId")&&this.entityId&&this.entityId!==this._lastEntityId)return this._lastEntityId=this.entityId,this._history=[],void this._fetchHistory().then((()=>{var t;this._chartReady&&this.visible&&(null===(t=this._chart)||void 0===t||t.resize(),this._updateChart(),this._initialViewSet=!1,this._applyInitialView())}));const e=["targetTemp","roomTemp","regulatedTemp","extTemp","powerPercent"].some((e=>t.has(e)));!e||null===this.targetTemp&&null===this.roomTemp&&null===this.powerPercent||(this._addLiveDataPoint(),this._chartReady&&this.visible&&this._updateChart())}async _fetchHistory(){if(!this.hass||!this.entityId)return;this._loading=!0;const t=new Date,e=`history/period/${new Date(t.getTime()-864e5).toISOString()}?filter_entity_id=${this.entityId}&end_time=${t.toISOString()}&significant_changes_only=false&minimal_response=false`;try{const t=await this.hass.callApi("GET",e);if(!Array.isArray(t)||0===t.length)return;const i=t[0].filter((t=>t.attributes&&t.last_updated)).map((t=>{var e,i,o,a,n,s,r,l,c,d,h,u,p,m,_,f,g,b,v,y,w,x,k;return{timestamp:new Date(t.last_updated).getTime(),targetTemp:null!==(e=t.attributes.temperature)&&void 0!==e?e:null,roomTemp:null!==(i=t.attributes.current_temperature)&&void 0!==i?i:null,regulatedTemp:null!==(l=null!==(s=null===(n=null===(a=null===(o=t.attributes)||void 0===o?void 0:o.vtherm_over_climate)||void 0===a?void 0:a.regulation)||void 0===n?void 0:n.regulated_target_temperature)&&void 0!==s?s:null===(r=t.attributes)||void 0===r?void 0:r.regulated_target_temperature)&&void 0!==l?l:null,extTemp:null!==(h=null===(d=null===(c=t.attributes)||void 0===c?void 0:c.specific_states)||void 0===d?void 0:d.ext_current_temperature)&&void 0!==h?h:null,powerPercent:null!==(k=null!==(v=null!==(f=null!==(p=null===(u=t.attributes)||void 0===u?void 0:u.power_percent)&&void 0!==p?p:null===(_=null===(m=t.attributes)||void 0===m?void 0:m.specific_states)||void 0===_?void 0:_.power_percent)&&void 0!==f?f:null===(b=null===(g=t.attributes)||void 0===g?void 0:g.vtherm_over_switch)||void 0===b?void 0:b.power_percent)&&void 0!==v?v:null===(x=null===(w=null===(y=t.attributes)||void 0===y?void 0:y.vtherm_over_climate)||void 0===w?void 0:w.valve_regulation)||void 0===x?void 0:x.power_percent)&&void 0!==k?k:null}})).filter((t=>null!==t.targetTemp||null!==t.roomTemp)),o=i.length>0?i[i.length-1].timestamp:0,a=this._history.filter((t=>t.timestamp>o));this._history=[...i,...a].slice(-rr.MAX_POINTS)}catch(t){console.error("[VtRegulationChart] History fetch failed:",t)}finally{this._loading=!1}}_addLiveDataPoint(){var t,e;const i=Date.now(),o=this._history[this._history.length-1],a={timestamp:i,targetTemp:this.targetTemp,roomTemp:this.roomTemp,regulatedTemp:null!==(t=this.regulatedTemp)&&void 0!==t?t:null,extTemp:null!==(e=this.extTemp)&&void 0!==e?e:null,powerPercent:this.powerPercent};o&&i-o.timestamp<3e4?this._history=[...this._history.slice(0,-1),a]:this._history=[...this._history,a].slice(-rr.MAX_POINTS)}_resolveColor(t,e){return getComputedStyle(this).getPropertyValue(t).trim()||e}async _initChart(){var t,e;if(!this._destroyed&&(this._canvas=null!==(e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("canvas"))&&void 0!==e?e:null,this._canvas))try{const[{Chart:t,registerables:e},{default:i}]=await Promise.all([Promise.resolve().then((function(){return p_})),Promise.resolve().then((function(){return kf}))]);if(await Promise.resolve().then((function(){return Wb})),this._destroyed)return;t.register(...e,i);const o=this._resolveColor("--primary-text-color","#e5e5e5"),a=this._resolveColor("--secondary-text-color","#9e9e9e"),n="rgba(128,128,128,0.18)";this._chart=new t(this._canvas,{type:"line",data:{datasets:[{label:"Consigne",data:[],borderColor:"#f9a21f",backgroundColor:"rgba(249,162,31,0.08)",borderWidth:2,pointRadius:0,pointHoverRadius:4,tension:.3,yAxisID:"yTemp"},{label:"Pièce",data:[],borderColor:"#3a9ff2",backgroundColor:"rgba(58,159,242,0.08)",borderWidth:2,pointRadius:0,po Line truncated
<div class="chart-wrapper"> <div class="chart-wrapper">
${this._loading?B`<div class="chart-loading"></div>`:""} ${this._loading?W`<div class="chart-loading"></div>`:""}
<canvas></canvas> <canvas></canvas>
<div class="zoom-btns"> <div class="zoom-btns">
<button class="reset-zoom-btn" @click=${()=>this._zoomTo2h()} title="Vue 2 heures">2h</button> <button class="reset-zoom-btn" @click=${()=>this._zoomTo2h()} title="Vue 2 heures">2h</button>
@@ -1285,13 +1285,13 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
@keyframes vt-spin { @keyframes vt-spin {
to { transform: translate(-50%, -50%) rotate(360deg); } to { transform: translate(-50%, -50%) rotate(360deg); }
} }
`}};lr.MAX_POINTS=1440,t([ut({attribute:!1})],lr.prototype,"hass",void 0),t([ut({type:String})],lr.prototype,"entityId",void 0),t([ut({type:Boolean})],lr.prototype,"visible",void 0),t([ut({type:Number})],lr.prototype,"targetTemp",void 0),t([ut({type:Number})],lr.prototype,"roomTemp",void 0),t([ut({type:Number})],lr.prototype,"regulatedTemp",void 0),t([ut({type:Number})],lr.prototype,"extTemp",void 0),t([ut({type:Number})],lr.prototype,"powerPercent",void 0),t([mt()],lr.prototype,"_history",void 0),t([mt()],lr.prototype,"_loading",void 0),lr=rr=t([ct("vt-regulation-chart")],lr);const cr={auto:"M18,11V12.5C21.19,12.5 23.09,16.05 21.33,18.71L20.24,17.62C21.06,15.96 19.85,14 18,14V15.5L15.75,13.25L18,11M18,22V20.5C14.81,20.5 12.91,16.95 14.67,14.29L15.76,15.38C14.94,17.04 16.15,19 18,19V17.5L20.25,19.75L18,22M19,3H18V1H16V3H8V1H6V3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H14C13.36,20.45 12.86,19.77 12.5,19H5V8H19V10.59C19.71,10.7 20.39,10.94 21,11.31V5A2,2 0 0,0 19,3Z",heat_cool:"M12,6V9L16,5L12,1V4A8,8 0 0,0 4,12C4,13.57 4.46,15.03 5.24,16.26L6.7,14.8C6.25,13.97 6,13 6,12A6,6 0 0,1 12,6M18.76,7.74L17.3,9.2C17.74,10.04 18,11 18,12A6,6 0 0,1 12,18V15L8,19L12,23V20A8,8 0 0,0 20,12C20,10.43 19.54,8.97 18.76,7.74Z",heat:"M17.66 11.2C17.43 10.9 17.15 10.64 16.89 10.38C16.22 9.78 15.46 9.35 14.82 8.72C13.33 7.26 13 4.85 13.95 3C13 3.23 12.17 3.75 11.46 4.32C8.87 6.4 7.85 10.07 9.07 13.22C9.11 13.32 9.15 13.42 9.15 13.55C9.15 13.77 9 13.97 8.8 14.05C8.57 14.15 8.33 14.09 8.14 13.93C8.08 13.88 8.04 13.83 8 13.76C6.87 12.33 6.69 10.28 7.45 8.64C5.78 10 4.87 12.3 5 14.47C5.06 14.97 5.12 15.47 5.29 15.97C5.43 16.57 5.7 17.17 6 17.7C7.08 19.43 8.95 20.67 10.96 20.92C13.1 21.19 15.39 20.8 17.03 19.32C18.86 17.66 19.5 15 18.56 12.72L18.43 12.46C18.22 12 17.66 11.2 17.66 11.2M14.5 17.5C14.22 17.74 13.76 18 13.4 18.1C12.28 18.5 11.16 17.94 10.5 17.28C11.69 17 12.4 16.12 12.61 15.23C12.78 14.43 12.46 13.77 12.33 13C12.21 12.26 12.23 11.63 12.5 10.94C12.69 11.32 12.89 11.7 13.13 12C13.9 13 15.11 13.44 15.37 14.8C15.41 14.94 15.43 15.08 15.43 15.23C15.46 16.05 15.1 16.95 14.5 17.5H14.5Z",cool:"M20.79,13.95L18.46,14.57L16.46,13.44V10.56L18.46,9.43L20.79,10.05L21.31,8.12L19.54,7.65L20,5.88L18.07,5.36L17.45,7.69L15.45,8.82L13,7.38V5.12L14.71,3.41L13.29,2L12,3.29L10.71,2L9.29,3.41L11,5.12V7.38L8.5,8.82L6.5,7.69L5.92,5.36L4,5.88L4.47,7.65L2.7,8.12L3.22,10.05L5.55,9.43L7.55,10.56V13.45L5.55,14.58L3.22,13.96L2.7,15.89L4.47,16.36L4,18.12L5.93,18.64L6.55,16.31L8.55,15.18L11,16.62V18.88L9.29,20.59L10.71,22L12,20.71L13.29,22L14.7,20.59L13,18.88V16.62L15.5,15.17L17.5,16.3L18.12,18.63L20,18.12L19.53,16.35L21.3,15.88L20.79,13.95M9.5,10.56L12,9.11L14.5,10.56V13.44L12,14.89L9.5,13.44V10.56Z",off:"M16.56,5.44L15.11,6.89C16.84,7.94 18,9.83 18,12A6,6 0 0,1 12,18A6,6 0 0,1 6,12C6,9.83 7.16,7.94 8.88,6.88L7.44,5.44C5.36,6.88 4,9.28 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12C20,9.28 18.64,6.88 16.56,5.44M13,3H11V13H13",fan_only:St,dry:Vt,window_open:Ht,windowBypass:Rt,presence:Ct,motion:$t,eco:"M17,8C8,10 5.9,16.17 3.82,21.34L5.71,22L6.66,19.7C7.14,19.87 7.64,20 8,20C19,20 22,3 22,3C21,5 14,5.25 9,6.25C4,7.25 2,11.5 2,13.5C2,15.5 3.75,17.25 3.75,17.25C7,8 17,8 17,8Z",comfort:"M12.5 7C12.5 5.89 13.39 5 14.5 5H18C19.1 5 20 5.9 20 7V9.16C18.84 9.57 18 10.67 18 11.97V14H12.5V7M6 11.96V14H11.5V7C11.5 5.89 10.61 5 9.5 5H6C4.9 5 4 5.9 4 7V9.15C5.16 9.56 6 10.67 6 11.96M20.66 10.03C19.68 10.19 19 11.12 19 12.12V15H5V12C5 10.9 4.11 10 3 10S1 10.9 1 12V17C1 18.1 1.9 19 3 19V21H5V19H19V21H21V19C22.1 19 23 18.1 23 17V12C23 10.79 21.91 9.82 20.66 10.03Z",boost:"M13.13 22.19L11.5 18.36C13.07 17.78 14.54 17 15.9 16.09L13.13 22.19M5.64 12.5L1.81 10.87L7.91 8.1C7 9.46 6.22 10.93 5.64 12.5M21.61 2.39C21.61 2.39 16.66 .269 11 5.93C8.81 8.12 7.5 10.53 6.65 12.64C6.37 13.39 6.56 14.21 7.11 14.77L9.24 16.89C9.79 17.45 10.61 17.63 11.36 17.35C13.5 16.53 15.88 15.19 18.07 13C23.73 7.34 21.61 2.39 21.61 2.39M14.54 9.46C13.76 8.68 13.76 7.41 14.54 6.63S16.59 5.85 17.37 6.63C18.14 7.41 18.15 8.68 17.37 9.46C16.59 10.24 15.32 10.24 14.54 9.46M8.88 16.53L7.47 15.12L8.88 16.53M6.24 22L9.88 18.36C9.54 18.27 9.21 18.12 8.91 17.91L4.83 22H6.24M2 22H3.41L8.18 17.24L6.76 15.83L2 20.59V22M2 19.17L6.09 15.09C5.88 14.79 5.73 14.47 5.64 14.12L2 17.76V19.17Z",frost:"M14.46 9.41L11 7.38V5.12L12.71 3.41L11.29 2L10 3.29L8.71 2L7.29 3.41L9 5.12V7.38L6.5 8.82L4.5 7.69L3.92 5.36L2 5.88L2.47 7.65L.7 8.12L1.22 10.05L3.55 9.43L5.55 10.56V13.45L3.55 14.58L1.22 13.96L.7 15.89L2.47 16.36L2 18.12L3.93 18.64L4.55 16.31L6.55 15.18L9 16.62V18.88L7.29 20.59L8.71 22L10 20.71L11.29 22L12.7 20.59L11 18.88V16.62L14.46 14.61M7.5 10.56L10 9.11L12.5 10.56V13.44L10 14.89L7.5 13.44M19 5C17.89 5 17 5.89 17 7V13.76C16.36 14.33 16 15.15 16 16C16 17.66 17.34 19 19 19S22 17.66 22 16C22 15.15 21.64 14.33 21 13.77V7C21 5.89 20.11 5 19 5M19 6C19.55 6 20 6.45 20 7V8H18V7C18 6.45 18.45 6 19 6",activity:$t,power:"M12 3L2 12H5V20H19V12H22L12 3M11.5 18V14H9L12.5 7V11H15L11.5 18Z",flashAlert:Mt,temperature:"M15 13V5A3 3 0 0 0 9 5V13A5 5 Line truncated `}};lr.MAX_POINTS=1440,t([pt({attribute:!1})],lr.prototype,"hass",void 0),t([pt({type:String})],lr.prototype,"entityId",void 0),t([pt({type:Boolean})],lr.prototype,"visible",void 0),t([pt({type:Number})],lr.prototype,"targetTemp",void 0),t([pt({type:Number})],lr.prototype,"roomTemp",void 0),t([pt({type:Number})],lr.prototype,"regulatedTemp",void 0),t([pt({type:Number})],lr.prototype,"extTemp",void 0),t([pt({type:Number})],lr.prototype,"powerPercent",void 0),t([mt()],lr.prototype,"_history",void 0),t([mt()],lr.prototype,"_loading",void 0),lr=rr=t([dt("vt-regulation-chart")],lr);const cr="unavailable",dr={auto:"M18,11V12.5C21.19,12.5 23.09,16.05 21.33,18.71L20.24,17.62C21.06,15.96 19.85,14 18,14V15.5L15.75,13.25L18,11M18,22V20.5C14.81,20.5 12.91,16.95 14.67,14.29L15.76,15.38C14.94,17.04 16.15,19 18,19V17.5L20.25,19.75L18,22M19,3H18V1H16V3H8V1H6V3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H14C13.36,20.45 12.86,19.77 12.5,19H5V8H19V10.59C19.71,10.7 20.39,10.94 21,11.31V5A2,2 0 0,0 19,3Z",heat_cool:"M12,6V9L16,5L12,1V4A8,8 0 0,0 4,12C4,13.57 4.46,15.03 5.24,16.26L6.7,14.8C6.25,13.97 6,13 6,12A6,6 0 0,1 12,6M18.76,7.74L17.3,9.2C17.74,10.04 18,11 18,12A6,6 0 0,1 12,18V15L8,19L12,23V20A8,8 0 0,0 20,12C20,10.43 19.54,8.97 18.76,7.74Z",heat:"M17.66 11.2C17.43 10.9 17.15 10.64 16.89 10.38C16.22 9.78 15.46 9.35 14.82 8.72C13.33 7.26 13 4.85 13.95 3C13 3.23 12.17 3.75 11.46 4.32C8.87 6.4 7.85 10.07 9.07 13.22C9.11 13.32 9.15 13.42 9.15 13.55C9.15 13.77 9 13.97 8.8 14.05C8.57 14.15 8.33 14.09 8.14 13.93C8.08 13.88 8.04 13.83 8 13.76C6.87 12.33 6.69 10.28 7.45 8.64C5.78 10 4.87 12.3 5 14.47C5.06 14.97 5.12 15.47 5.29 15.97C5.43 16.57 5.7 17.17 6 17.7C7.08 19.43 8.95 20.67 10.96 20.92C13.1 21.19 15.39 20.8 17.03 19.32C18.86 17.66 19.5 15 18.56 12.72L18.43 12.46C18.22 12 17.66 11.2 17.66 11.2M14.5 17.5C14.22 17.74 13.76 18 13.4 18.1C12.28 18.5 11.16 17.94 10.5 17.28C11.69 17 12.4 16.12 12.61 15.23C12.78 14.43 12.46 13.77 12.33 13C12.21 12.26 12.23 11.63 12.5 10.94C12.69 11.32 12.89 11.7 13.13 12C13.9 13 15.11 13.44 15.37 14.8C15.41 14.94 15.43 15.08 15.43 15.23C15.46 16.05 15.1 16.95 14.5 17.5H14.5Z",cool:"M20.79,13.95L18.46,14.57L16.46,13.44V10.56L18.46,9.43L20.79,10.05L21.31,8.12L19.54,7.65L20,5.88L18.07,5.36L17.45,7.69L15.45,8.82L13,7.38V5.12L14.71,3.41L13.29,2L12,3.29L10.71,2L9.29,3.41L11,5.12V7.38L8.5,8.82L6.5,7.69L5.92,5.36L4,5.88L4.47,7.65L2.7,8.12L3.22,10.05L5.55,9.43L7.55,10.56V13.45L5.55,14.58L3.22,13.96L2.7,15.89L4.47,16.36L4,18.12L5.93,18.64L6.55,16.31L8.55,15.18L11,16.62V18.88L9.29,20.59L10.71,22L12,20.71L13.29,22L14.7,20.59L13,18.88V16.62L15.5,15.17L17.5,16.3L18.12,18.63L20,18.12L19.53,16.35L21.3,15.88L20.79,13.95M9.5,10.56L12,9.11L14.5,10.56V13.44L12,14.89L9.5,13.44V10.56Z",off:"M16.56,5.44L15.11,6.89C16.84,7.94 18,9.83 18,12A6,6 0 0,1 12,18A6,6 0 0,1 6,12C6,9.83 7.16,7.94 8.88,6.88L7.44,5.44C5.36,6.88 4,9.28 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12C20,9.28 18.64,6.88 16.56,5.44M13,3H11V13H13",fan_only:Tt,dry:Vt,window_open:Ht,windowBypass:It,presence:Ct,motion:$t,eco:"M17,8C8,10 5.9,16.17 3.82,21.34L5.71,22L6.66,19.7C7.14,19.87 7.64,20 8,20C19,20 22,3 22,3C21,5 14,5.25 9,6.25C4,7.25 2,11.5 2,13.5C2,15.5 3.75,17.25 3.75,17.25C7,8 17,8 17,8Z",comfort:"M12.5 7C12.5 5.89 13.39 5 14.5 5H18C19.1 5 20 5.9 20 7V9.16C18.84 9.57 18 10.67 18 11.97V14H12.5V7M6 11.96V14H11.5V7C11.5 5.89 10.61 5 9.5 5H6C4.9 5 4 5.9 4 7V9.15C5.16 9.56 6 10.67 6 11.96M20.66 10.03C19.68 10.19 19 11.12 19 12.12V15H5V12C5 10.9 4.11 10 3 10S1 10.9 1 12V17C1 18.1 1.9 19 3 19V21H5V19H19V21H21V19C22.1 19 23 18.1 23 17V12C23 10.79 21.91 9.82 20.66 10.03Z",boost:"M13.13 22.19L11.5 18.36C13.07 17.78 14.54 17 15.9 16.09L13.13 22.19M5.64 12.5L1.81 10.87L7.91 8.1C7 9.46 6.22 10.93 5.64 12.5M21.61 2.39C21.61 2.39 16.66 .269 11 5.93C8.81 8.12 7.5 10.53 6.65 12.64C6.37 13.39 6.56 14.21 7.11 14.77L9.24 16.89C9.79 17.45 10.61 17.63 11.36 17.35C13.5 16.53 15.88 15.19 18.07 13C23.73 7.34 21.61 2.39 21.61 2.39M14.54 9.46C13.76 8.68 13.76 7.41 14.54 6.63S16.59 5.85 17.37 6.63C18.14 7.41 18.15 8.68 17.37 9.46C16.59 10.24 15.32 10.24 14.54 9.46M8.88 16.53L7.47 15.12L8.88 16.53M6.24 22L9.88 18.36C9.54 18.27 9.21 18.12 8.91 17.91L4.83 22H6.24M2 22H3.41L8.18 17.24L6.76 15.83L2 20.59V22M2 19.17L6.09 15.09C5.88 14.79 5.73 14.47 5.64 14.12L2 17.76V19.17Z",frost:"M14.46 9.41L11 7.38V5.12L12.71 3.41L11.29 2L10 3.29L8.71 2L7.29 3.41L9 5.12V7.38L6.5 8.82L4.5 7.69L3.92 5.36L2 5.88L2.47 7.65L.7 8.12L1.22 10.05L3.55 9.43L5.55 10.56V13.45L3.55 14.58L1.22 13.96L.7 15.89L2.47 16.36L2 18.12L3.93 18.64L4.55 16.31L6.55 15.18L9 16.62V18.88L7.29 20.59L8.71 22L10 20.71L11.29 22L12.7 20.59L11 18.88V16.62L14.46 14.61M7.5 10.56L10 9.11L12.5 10.56V13.44L10 14.89L7.5 13.44M19 5C17.89 5 17 5.89 17 7V13.76C16.36 14.33 16 15.15 16 16C16 17.66 17.34 19 19 19S22 17.66 22 16C22 15.15 21.64 14.33 21 13.77V7C21 5.89 20.11 5 19 5M19 6C19.55 6 20 6.45 20 7V8H18V7C18 6.45 18.45 6 19 6",activity:$t,power:"M12 3L2 12H5V20H19V12H22L12 3M11.5 18V14H9L12.5 7V11H15L11.5 18Z",flashAlert:Mt,temperature:"M15 13V5A3 3 Line truncated
<div class="regulation-chart-panel"> <div class="regulation-chart-panel">
<div <div
class="regulation-chart-header" class="regulation-chart-header"
@click=${()=>{this._regulationChartOpen=!this._regulationChartOpen}} @click=${()=>{this._regulationChartOpen=!this._regulationChartOpen}}
> >
<span class="regulation-chart-title">${_n({hass:this.hass,string:"extra_states.regulation_chart_title"})}</span> <span class="regulation-chart-title">${ma({hass:this.hass,string:"extra_states.regulation_chart_title"})}</span>
<ha-svg-icon <ha-svg-icon
class="regulation-chart-chevron" class="regulation-chart-chevron"
.path=${this._regulationChartOpen?wt:xt} .path=${this._regulationChartOpen?wt:xt}
@@ -1303,99 +1303,107 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
.entityId=${null!==(i=null===(e=this._config)||void 0===e?void 0:e.entity)&&void 0!==i?i:""} .entityId=${null!==(i=null===(e=this._config)||void 0===e?void 0:e.entity)&&void 0!==i?i:""}
.visible=${this._regulationChartOpen} .visible=${this._regulationChartOpen}
.targetTemp=${null!==(o=this.temperature)&&void 0!==o?o:null} .targetTemp=${null!==(o=this.temperature)&&void 0!==o?o:null}
.roomTemp=${null!==(n=this.current)&&void 0!==n?n:null} .roomTemp=${null!==(a=this.current)&&void 0!==a?a:null}
.regulatedTemp=${this.regulatedTargetTemperature} .regulatedTemp=${this.regulatedTargetTemperature}
.extTemp=${null!==(u=null===(h=null===(d=null===(c=null===(s=null===(a=this.hass)||void 0===a?void 0:a.states)||void 0===s?void 0:s[null!==(l=null===(r=this._config)||void 0===r?void 0:r.entity)&&void 0!==l?l:""])||void 0===c?void 0:c.attributes)||void 0===d?void 0:d.specific_states)||void 0===h?void 0:h.ext_current_temperature)&&void 0!==u?u:null} .extTemp=${null!==(u=null===(h=null===(d=null===(c=null===(s=null===(n=this.hass)||void 0===n?void 0:n.states)||void 0===s?void 0:s[null!==(l=null===(r=this._config)||void 0===r?void 0:r.entity)&&void 0!==l?l:""])||void 0===c?void 0:c.attributes)||void 0===d?void 0:d.specific_states)||void 0===h?void 0:h.ext_current_temperature)&&void 0!==u?u:null}
.powerPercent=${null!==(m=this.powerPercent)&&void 0!==m?m:null} .powerPercent=${null!==(p=this.powerPercent)&&void 0!==p?p:null}
></vt-regulation-chart> ></vt-regulation-chart>
</div> </div>
</div> </div>
`:B``}_renderPresetModificationPanel(){var t;if(!(null===(t=this._config)||void 0===t?void 0:t.allow_preset_modification))return B``;const e=["frost","eco","comfort","boost"],i={frost:_n({hass:this.hass,string:"extra_states.frost"}),eco:_n({hass:this.hass,string:"extra_states.eco"}),comfort:_n({hass:this.hass,string:"extra_states.comfort"}),boost:_n({hass:this.hass,string:"extra_states.boost"})},o=new Map;for(const t of this._presetTempEntities){const e=`${t.mode}_${t.away?"away":"present"}_${t.preset}`;o.set(e,t.entityId)}const n=[{mode:"heat",away:!1,labelKey:"extra_states.preset_row_heat"},{mode:"heat",away:!0,labelKey:"extra_states.preset_row_heat_away"},{mode:"cool",away:!1,labelKey:"extra_states.preset_row_cool"},{mode:"cool",away:!0,labelKey:"extra_states.preset_row_cool_away"}].filter((t=>e.some((e=>o.has(`${t.mode}_${t.away?"away":"present"}_${e}`))))),a=this._presetTempEntities.length>0,s=(t,e,i)=>{var n,a,s,r,l,c,d;const h=`${t}_${e?"away":"present"}_${i}`,u=o.get(h);if(!u)return B`<td class="preset-temp-cell empty">–</td>`;const m=null===(n=this.hass)||void 0===n?void 0:n.states[u],p=m?parseFloat(m.state):null,_=null!==(s=null===(a=null==m?void 0:m.attributes)||void 0===a?void 0:a.step)&&void 0!==s?s:.5,g=null!==(l=null===(r=null==m?void 0:m.attributes)||void 0===r?void 0:r.min)&&void 0!==l?l:7,f=null!==(d=null===(c=null==m?void 0:m.attributes)||void 0===c?void 0:c.max)&&void 0!==d?d:35,b=t=>{const e=Math.round(Math.min(f,Math.max(g,t))/_)*_,i=Math.round(100*e)/100;this.hass.callService("number","set_value",{entity_id:u,value:i})};return B` `:W``}_renderPresetModificationPanel(){var t;if(!(null===(t=this._config)||void 0===t?void 0:t.allow_preset_modification))return W``;const e=["frost","eco","comfort","boost"],i={frost:ma({hass:this.hass,string:"extra_states.frost"}),eco:ma({hass:this.hass,string:"extra_states.eco"}),comfort:ma({hass:this.hass,string:"extra_states.comfort"}),boost:ma({hass:this.hass,string:"extra_states.boost"})},o=new Map;for(const t of this._presetTempEntities){const e=`${t.mode}_${t.away?"away":"present"}_${t.preset}`;o.set(e,t.entityId)}const a=this._hasValidCentralPresetTemperatures(),n=this._presetTempEntities.some((t=>{var e;const i=null===(e=this.hass)||void 0===e?void 0:e.states[t.entityId];return!!i&&i.state!==cr})),s=this.hvacMode===pr?"cool":"heat";let r=[{mode:"heat",away:!1,labelKey:"extra_states.preset_row_heat"},{mode:"heat",away:!0,labelKey:"extra_states.preset_row_heat_away"},{mode:"cool",away:!1,labelKey:"extra_states.preset_row_cool"},{mode:"cool",away:!0,labelKey:"extra_states.preset_row_cool_away"}];r=r.filter((t=>t.mode===s)),n?r=r.filter((t=>e.some((e=>o.has(`${t.mode}_${t.away?"away":"present"}_${e}`))))):a||(r=[]);const l=n||a,c=(t,e,i)=>{var s,r,l,c,d,h;const u=`${t}_${e?"away":"present"}_${i}`,p=o.get(u),m=p?this.hass.states[p]:void 0,_=!!m&&m.state!==cr;if(p&&_){const t=parseFloat(m.state),e=null!==(r=null===(s=null==m?void 0:m.attributes)||void 0===s?void 0:s.step)&&void 0!==r?r:.5,o=null!==(c=null===(l=null==m?void 0:m.attributes)||void 0===l?void 0:l.min)&&void 0!==c?c:7,a=null!==(h=null===(d=null==m?void 0:m.attributes)||void 0===d?void 0:d.max)&&void 0!==h?h:35,n=t=>{const i=Math.round(Math.min(a,Math.max(o,t))/e)*e,n=Math.round(100*i)/100;this.hass.callService("number","set_value",{entity_id:p,value:n})};return W`
<td class="preset-temp-cell preset-col-${i}"> <td class="preset-temp-cell preset-col-${i}">
<div class="preset-temp-stepper"> <div class="preset-temp-stepper">
<input <input
type="number" type="number"
class="preset-temp-input" class="preset-temp-input"
.value=${null===p||isNaN(p)?"":String(p)} .value=${null===t||isNaN(t)?"":String(t)}
step=${_} step=${e}
min=${g} min=${o}
max=${f} max=${a}
@change=${t=>{const e=parseFloat(t.target.value);isNaN(e)||b(e)}} @change=${t=>{const e=parseFloat(t.target.value);isNaN(e)||n(e)}}
/> />
<div class="preset-step-btns"> <div class="preset-step-btns">
<button class="preset-step-btn preset-step-up" @click=${()=>{null===p||isNaN(p)||b(p+_)}}>+</button> <button class="preset-step-btn preset-step-up" @click=${()=>{null===t||isNaN(t)||n(t+e)}}>+</button>
<button class="preset-step-btn preset-step-down" @click=${()=>{null===p||isNaN(p)||b(p-_)}}>−</button> <button class="preset-step-btn preset-step-down" @click=${()=>{null===t||isNaN(t)||n(t-e)}}>−</button>
</div> </div>
</div> </div>
</td> </td>
`};return B` `}if(!n&&a){const o=this._getPresetTemperature(i,t,e,!1);if(null!==o)return W`
<td class="preset-temp-cell preset-col-${i}">
<div class="preset-temp-stepper">
<div class="preset-temp-readonly">
${Ta(o,this.hass.locale,{minimumFractionDigits:1,maximumFractionDigits:1})} ${this.hass.config.unit_system.temperature}
</div>
</div>
</td>
`}return W`<td class="preset-temp-cell empty">–</td>`};return W`
<div class="preset-mod-panel ${this._isLocked?"locked":""}"> <div class="preset-mod-panel ${this._isLocked?"locked":""}">
<div <div
class="preset-mod-header" class="preset-mod-header"
@click=${()=>{this._isLocked||(this._presetsPanelOpen=!this._presetsPanelOpen)}} @click=${()=>{this._isLocked||(this._presetsPanelOpen=!this._presetsPanelOpen)}}
title=${_n({hass:this.hass,string:"extra_states.preset_mod_title"})} title=${ma({hass:this.hass,string:"extra_states.preset_mod_title"})}
> >
<span class="preset-mod-title">${_n({hass:this.hass,string:"extra_states.preset_mod_title"})}</span> <span class="preset-mod-title">${ma({hass:this.hass,string:"extra_states.preset_mod_title"})}</span>
<ha-svg-icon <ha-svg-icon
class="preset-mod-chevron ${this._presetsPanelOpen?"open":""}" class="preset-mod-chevron ${this._presetsPanelOpen?"open":""}"
.path=${this._presetsPanelOpen?wt:xt} .path=${this._presetsPanelOpen?wt:xt}
></ha-svg-icon> ></ha-svg-icon>
</div> </div>
${this._presetsPanelOpen?B` ${this._presetsPanelOpen?W`
<div class="preset-mod-body"> <div class="preset-mod-body">
${a?B` ${l?W`
<table class="preset-temp-table"> <table class="preset-temp-table">
<thead> <thead>
<tr> <tr>
<th class="preset-temp-row-label"></th> <th class="preset-temp-row-label"></th>
${e.map((t=>B`<th class="preset-temp-col-label col-${t}">${i[t]}</th>`))} ${e.map((t=>W`<th class="preset-temp-col-label col-${t}">${i[t]}</th>`))}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
${n.map((t=>B` ${r.map((t=>W`
<tr> <tr>
<td class="preset-temp-row-label"> <td class="preset-temp-row-label">
${_n({hass:this.hass,string:t.labelKey})} ${ma({hass:this.hass,string:t.labelKey})}
</td> </td>
${e.map((e=>s(t.mode,t.away,e)))} ${e.map((e=>c(t.mode,t.away,e)))}
</tr> </tr>
`))} `))}
</tbody> </tbody>
</table> </table>
`:B` `:W`
<div class="preset-mod-empty"> <div class="preset-mod-empty">
${_n({hass:this.hass,string:"extra_states.preset_mod_no_entities"})} ${ma({hass:this.hass,string:"extra_states.preset_mod_no_entities"})}
</div> </div>
`} `}
</div> </div>
`:""} `:""}
</div> </div>
`}_renderClassicContent(t=!1){var e,i,o,n,a,s,r,l,c,d,h,u,m,p,_,g,f,b,v,y,w,x,k;const T=!t&&this.effectiveDisableCircle,S=!t&&this.effectiveDisableBackgroundColor;this._renderingAsClassic=t;const M=B` `}_renderClassicContent(t=!1){var e,i,o,a,n,s,r,l,c,d,h,u,p,m,_,f,g,b,v,y,w,x,k;const S=!t&&this.effectiveDisableCircle,T=!t&&this.effectiveDisableBackgroundColor;this._renderingAsClassic=t;const M=W`
${this.name.length>0?B` ${this.name.length>0?W`
<div class="name">${this.name}</div> <div class="name">${this.name}</div>
`:""} `:""}
${(null===(e=this.safety_state)||void 0===e?void 0:e.length)>0&&!this.displayMessages?B` ${(null===(e=this.safety_state)||void 0===e?void 0:e.length)>0&&!this.displayMessages?W`
<div class="security"> <div class="security">
<ha-icon-button class="alert" .path=${Ot}> <ha-icon-button class="alert" .path=${Ot}>
</ha-icon-button> </ha-icon-button>
${B` ${W`
${this.safety_state.map((t=>B`<span>${t.name}: ${t.security_msg}</span>`))} ${this.safety_state.map((t=>W`<span>${t.name}: ${t.security_msg}</span>`))}
`} `}
</div> </div>
`:""} `:""}
${this.messages.length>0&&this.displayMessages?B` ${this.messages.length>0&&this.displayMessages?W`
<div class="messages"> <div class="messages">
<ha-icon-button class="alert" .path=${this._hasError?yt:At}> <ha-icon-button class="alert" .path=${this._hasError?yt:At}>
</ha-icon-button> </ha-icon-button>
${this.messages.map((t=>B`<span>${t}</span>`))} ${this.messages.map((t=>W`<span>${t}</span>`))}
</div> </div>
`:""} `:""}
<div title="${this.buildTitle()}" class="${T?"disabled-circle-container":""} ${S?"no-background-color":""} ${this.hvacMode}_${this.hvacAction} ${this._hasWindow?"window_open":""} ${this.overpowering?"overpowering":""}"> <div title="${this.buildTitle()}" class="${S?"disabled-circle-container":""} ${T?"no-background-color":""} ${this.hvacMode}_${this.hvacAction} ${this._hasWindow?"window_open":""} ${this.overpowering?"overpowering":""}">
${T?B` ${S?W`
<!-- No circle configured --> <!-- No circle configured -->
`:null!=this.value.low&&null!=this.value.high&&"unavailable"!==(null===(i=this.stateObj)||void 0===i?void 0:i.state)?B` `:null!=this.value.low&&null!=this.value.high&&(null===(i=this.stateObj)||void 0===i?void 0:i.state)!==cr?W`
<vt-ha-control-circular-slider <vt-ha-control-circular-slider
class="${null!==this.safety_state||this.displayMessages?"security_msg":""} ${this._hasWindow?"window_open":""} ${this.overpowering?"overpowering":""} ${this.presence?"presence":""} ${this.motion?"motion":""} ${this._hasWindowByPass?"windowByPass":""} ${(null===(o=this._config)||void 0===o?void 0:o.show_background_gradient_on_active)&&this.isDeviceActive?"with-background-gradient":""}" class="${null!==this.safety_state||this.displayMessages?"security_msg":""} ${this._hasWindow?"window_open":""} ${this.overpowering?"overpowering":""} ${this.presence?"presence":""} ${this.motion?"motion":""} ${this._hasWindowByPass?"windowByPass":""} ${(null===(o=this._config)||void 0===o?void 0:o.show_background_gradient_on_active)&&this.isDeviceActive?"with-background-gradient":""}"
.inactive=${this._hasWindow} .inactive=${this._hasWindow}
@@ -1411,9 +1419,9 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
@high-changed=${this._highChanged} @high-changed=${this._highChanged}
@high-changing=${this._highChanging} @high-changing=${this._highChanging}
> >
`:B` `:W`
<vt-ha-control-circular-slider <vt-ha-control-circular-slider
class="${null!==this.safety_state||this.displayMessages?"security_msg":""} ${this._hasWindow?"window_open":""} ${this.overpowering?"overpowering":""} ${this.presence?"presence":""} ${this.motion?"motion":""} ${this._hasWindowByPass?"windowByPass":""} ${(null===(n=this._config)||void 0===n?void 0:n.show_background_gradient_on_active)&&this.isDeviceActive?"with-background-gradient":""}" class="${null!==this.safety_state||this.displayMessages?"security_msg":""} ${this._hasWindow?"window_open":""} ${this.overpowering?"overpowering":""} ${this.presence?"presence":""} ${this.motion?"motion":""} ${this._hasWindowByPass?"windowByPass":""} ${(null===(a=this._config)||void 0===a?void 0:a.show_background_gradient_on_active)&&this.isDeviceActive?"with-background-gradient":""}"
.inactive=${this._hasWindow} .inactive=${this._hasWindow}
.mode="start" .mode="start"
@value-changed=${this._highChanged} @value-changed=${this._highChanged}
@@ -1425,45 +1433,45 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
max=${this.max} max=${this.max}
> >
`} `}
<div class="content${(null===(a=this._config)||void 0===a?void 0:a.disable_presets)?" no-presets":""} ${0==this.name.length?" noname":""} ${null!==this.safety_state||this.displayMessages?" security_msg":""} ${this._hasWindow?" window_open":""} ${this.overpowering?" overpowering":""} ${this.presence?" presence":""} ${this.motion?" motion":""} ${this._hasWindowByPass?" windowByPass":""} " > <div class="content${(null===(n=this._config)||void 0===n?void 0:n.disable_presets)?" no-presets":""} ${0==this.name.length?" noname":""} ${null!==this.safety_state||this.displayMessages?" security_msg":""} ${this._hasWindow?" window_open":""} ${this.overpowering?" overpowering":""} ${this.presence?" presence":""} ${this.motion?" motion":""} ${this._hasWindowByPass?" windowByPass":""} " >
<svg id="main" viewbox="0 0 125 100"> <svg id="main" viewbox="0 0 125 100">
<g transform="translate(57.5,37) scale(0.35)"> <g transform="translate(57.5,37) scale(0.35)">
${this._hasWindowByPass?j` ${this._hasWindowByPass?B`
<g transform="${this._hasWindowByPass?"translate(-50.25,0)":""}" @click=${this._handleToggleWindowByPass} class="icon-group"> <g transform="${this._hasWindowByPass?"translate(-50.25,0)":""}" @click=${this._handleToggleWindowByPass} class="icon-group">
<rect width="24" height="24" fill="transparent" style="cursor: pointer;"/> <rect width="24" height="24" fill="transparent" style="cursor: pointer;"/>
<path class="window window-by-pass ${this._hasWindowByPass?"active":""}" id="window-by-pass" d=${Rt}/> <path class="window window-by-pass ${this._hasWindowByPass?"active":""}" id="window-by-pass" d=${It}/>
</g> </g>
`:""} `:""}
${this._hasWindowByPass||!this._hasWindow||(null===(s=this._config)||void 0===s?void 0:s.disable_window)?"":j` ${this._hasWindowByPass||!this._hasWindow||(null===(s=this._config)||void 0===s?void 0:s.disable_window)?"":B`
<g transform="${this._hasWindow&&!(null===(r=this._config)||void 0===r?void 0:r.disable_window)?"translate(-50.25,0)":""}" @click=${this._handleToggleWindowByPass} class="icon-group"> <g transform="${this._hasWindow&&!(null===(r=this._config)||void 0===r?void 0:r.disable_window)?"translate(-50.25,0)":""}" @click=${this._handleToggleWindowByPass} class="icon-group">
<rect width="24" height="24" fill="transparent" style="cursor: pointer;"/> <rect width="24" height="24" fill="transparent" style="cursor: pointer;"/>
<path class="window ${this._hasWindow?"active":""}" id="window" d=${Ht}/> <path class="window ${this._hasWindow?"active":""}" id="window" d=${Ht}/>
</g> </g>
`} `}
${this._hasOverpowering&&!(null===(l=this._config)||void 0===l?void 0:l.disable_overpowering)?j` ${this._hasOverpowering&&!(null===(l=this._config)||void 0===l?void 0:l.disable_overpowering)?B`
<path class="overpowering ${this.overpowering?"active":""}" transform="${this._hasOverpowering&&!(null===(c=this._config)||void 0===c?void 0:c.disable_overpowering)?"translate(-25.25,0)":""}" id="overpowering" d=${Mt} /> <path class="overpowering ${this.overpowering?"active":""}" transform="${this._hasOverpowering&&!(null===(c=this._config)||void 0===c?void 0:c.disable_overpowering)?"translate(-25.25,0)":""}" id="overpowering" d=${Mt} />
`:""} `:""}
${this._hasPresence?j` ${this._hasPresence?B`
<path class="presence ${this.presence?"active":""}" transform="${this._hasPresence?"translate(0.25,0)":""}" id="overpowering" d=${Ct} /> <path class="presence ${this.presence?"active":""}" transform="${this._hasPresence?"translate(0.25,0)":""}" id="overpowering" d=${Ct} />
`:""} `:""}
${this._hasAutoStartStop&&!(null===(d=this._config)||void 0===d?void 0:d.disable_autoStartStop)?j` ${this._hasAutoStartStop&&!(null===(d=this._config)||void 0===d?void 0:d.disable_autoStartStop)?B`
<path class="auto-start-stop" transform="${this._hasAutoStartStop&&!(null===(h=this._config)||void 0===h?void 0:h.disable_autoStartStop)?"translate(25.25,0)":""}" id="autoStartStop" d=${zt}/> <path class="auto-start-stop" transform="${this._hasAutoStartStop&&!(null===(h=this._config)||void 0===h?void 0:h.disable_autoStartStop)?"translate(25.25,0)":""}" id="autoStartStop" d=${zt}/>
`:""} `:""}
${this._hasMotion?j` ${this._hasMotion?B`
<path class="motion ${this.motion?"active":""}" transform="${this._hasMotion?"translate(50.25,0)":""}" id="motion" d=${$t} /> <path class="motion ${this.motion?"active":""}" transform="${this._hasMotion?"translate(50.25,0)":""}" id="motion" d=${$t} />
`:""} `:""}
</g> </g>
${T?j` ${S?B`
${this._renderStatusText("62.5","50")} ${this._renderStatusText("62.5","50")}
${this._renderTemperature(this._display_top,!0,"55","62%",!(null===(u=null==this?void 0:this._config)||void 0===u?void 0:u.set_current_as_main))} ${this._renderTemperature(this._display_top,!0,"55","62%",!(null===(u=null==this?void 0:this._config)||void 0===u?void 0:u.set_current_as_main))}
${this._renderTemperature(this._display_bottom,!1,"90","62%",1==(null===(m=null==this?void 0:this._config)||void 0===m?void 0:m.set_current_as_main))} ${this._renderTemperature(this._display_bottom,!1,"90","62%",1==(null===(p=null==this?void 0:this._config)||void 0===p?void 0:p.set_current_as_main))}
<g class="current-info" transform="translate(100,65)"> <g class="current-info" transform="translate(100,65)">
${this._renderHVACAction()} ${this._renderHVACAction()}
</g> </g>
`:j` `:B`
${this._renderStatusText("62.5","50")} ${this._renderStatusText("62.5","50")}
${this._renderTemperature(this._display_top,!0,"50%","62%",!(null===(p=null==this?void 0:this._config)||void 0===p?void 0:p.set_current_as_main))} ${this._renderTemperature(this._display_top,!0,"50%","62%",!(null===(m=null==this?void 0:this._config)||void 0===m?void 0:m.set_current_as_main))}
<line x1="35" y1="72" x2="90" y2="72" stroke="#e7e7e8" stroke-width="0.5" /> <line x1="35" y1="72" x2="90" y2="72" stroke="#e7e7e8" stroke-width="0.5" />
<g class="current-info" transform="translate(62.5,80)"> <g class="current-info" transform="translate(62.5,80)">
${this._renderTemperature(this._display_bottom,!1,"-5%","0%",1==(null===(_=null==this?void 0:this._config)||void 0===_?void 0:_.set_current_as_main))} ${this._renderTemperature(this._display_bottom,!1,"-5%","0%",1==(null===(_=null==this?void 0:this._config)||void 0===_?void 0:_.set_current_as_main))}
@@ -1472,15 +1480,15 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
`} `}
</svg> </svg>
</div> </div>
${T?"":B` ${S?"":W`
</vt-ha-control-circular-slider>`} </vt-ha-control-circular-slider>`}
</div> </div>
<div id="modes" class="${null!==this.safety_state||this.displayMessages?"security_msg":""}"> <div id="modes" class="${null!==this.safety_state||this.displayMessages?"security_msg":""}">
${j` ${B`
${this.modes.map((t=>{var e,i,o,n,a,s,r,l;return(null===(e=this._config)||void 0===e?void 0:e.disable_heat)&&"heat"===t||(null===(i=this._config)||void 0===i?void 0:i.disable_auto)&&"auto"===t||(null===(o=this._config)||void 0===o?void 0:o.disable_cool)&&"cool"===t||(null===(n=this._config)||void 0===n?void 0:n.disable_heat_cool)&&"heat_cool"===t||(null===(a=this._config)||void 0===a?void 0:a.disable_dry)&&"dry"===t||(null===(s=this._config)||void 0===s?void 0:s.disable_fan_only)&&"fan_only"===t||(null===(r=this._config)||void 0===r?void 0:r.disable_off)&&"off"===t||(null===(l=this._config)||void 0===l?void 0:l.disable_sleep)&&"sleep"===t?B``:this._renderIcon(t,this.hvacMode)}))} ${this.modes.map((t=>{var e,i,o,a,n,s,r,l;return(null===(e=this._config)||void 0===e?void 0:e.disable_heat)&&"heat"===t||(null===(i=this._config)||void 0===i?void 0:i.disable_auto)&&"auto"===t||(null===(o=this._config)||void 0===o?void 0:o.disable_cool)&&"cool"===t||(null===(a=this._config)||void 0===a?void 0:a.disable_heat_cool)&&"heat_cool"===t||(null===(n=this._config)||void 0===n?void 0:n.disable_dry)&&"dry"===t||(null===(s=this._config)||void 0===s?void 0:s.disable_fan_only)&&"fan_only"===t||(null===(r=this._config)||void 0===r?void 0:r.disable_off)&&"off"===t||(null===(l=this._config)||void 0===l?void 0:l.disable_sleep)&&"sleep"===t?W``:this._renderIcon(t,this.hvacMode)}))}
`} `}
</div> </div>
${(null===(g=null==this?void 0:this._config)||void 0===g?void 0:g.disable_buttons)?B``:B` ${(null===(f=null==this?void 0:this._config)||void 0===f?void 0:f.disable_buttons)?W``:W`
<div id="vt-control-buttons" class="${null!==this.safety_state||this.displayMessages?"security_msg":""}"> <div id="vt-control-buttons" class="${null!==this.safety_state||this.displayMessages?"security_msg":""}">
<div class="button"> <div class="button">
<vt-ha-outlined-icon-button <vt-ha-outlined-icon-button
@@ -1503,23 +1511,23 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
</div> </div>
`} `}
${(null===(f=this._config)||void 0===f?void 0:f.disable_presets)?"":B` ${(null===(g=this._config)||void 0===g?void 0:g.disable_presets)?"":W`
<div id="presets" class="${null!==this.safety_state||this.displayMessages?"security_msg":""}"> <div id="presets" class="${null!==this.safety_state||this.displayMessages?"security_msg":""}">
${j` ${B`
${this.presets.map((t=>this._renderPreset(t,this.preset)))} ${this.presets.map((t=>this._renderPreset(t,this.preset)))}
`} `}
${(null===(b=this._config)||void 0===b?void 0:b.disable_timed_preset)?"":B` ${(null===(b=this._config)||void 0===b?void 0:b.disable_timed_preset)?"":W`
<div class="timed-preset-container ${this._isLocked?"locked":""}"> <div class="timed-preset-container ${this._isLocked?"locked":""}">
${this.timedPresetActive?B` ${this.timedPresetActive?W`
<span class="timed-preset-remaining" <span class="timed-preset-remaining"
title="${_n({hass:this.hass,string:"extra_states.cancel_timed_preset"})}" title="${ma({hass:this.hass,string:"extra_states.cancel_timed_preset"})}"
@click=${this._handleCancelTimedPreset}> @click=${this._handleCancelTimedPreset}>
${this._formatRemainingTime(this.timedPresetRemainingTime)} ${this._formatRemainingTime(this.timedPresetRemainingTime)}
</span> </span>
${(null!==(v=this.timedPresetRemainingTime)&&void 0!==v?v:0)<60?B` ${(null!==(v=this.timedPresetRemainingTime)&&void 0!==v?v:0)<60?W`
<span class="timed-preset-label">${_n({hass:this.hass,string:"extra_states.minutes"})}</span> <span class="timed-preset-label">${ma({hass:this.hass,string:"extra_states.minutes"})}</span>
`:""} `:""}
`:(null===(y=this._config)||void 0===y?void 0:y.use_manual_duration_input)?B` `:(null===(y=this._config)||void 0===y?void 0:y.use_manual_duration_input)?W`
<input <input
type="number" type="number"
class="timed-preset-input ${this.timedPresetDuration?"active":""}" class="timed-preset-input ${this.timedPresetDuration?"active":""}"
@@ -1528,18 +1536,18 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
placeholder="0" placeholder="0"
min="0" min="0"
max="1440" max="1440"
title="${_n({hass:this.hass,string:"extra_states.timed_preset_title"})}" title="${ma({hass:this.hass,string:"extra_states.timed_preset_title"})}"
/> />
<span class="timed-preset-label">${_n({hass:this.hass,string:"extra_states.minutes"})}</span> <span class="timed-preset-label">${ma({hass:this.hass,string:"extra_states.minutes"})}</span>
`:B` `:W`
<select <select
class="timed-preset-select ${this.timedPresetDuration?"active":""}" class="timed-preset-select ${this.timedPresetDuration?"active":""}"
@change=${this._handleTimedPresetSelectChange} @change=${this._handleTimedPresetSelectChange}
title="${_n({hass:this.hass,string:"extra_states.timed_preset_title"})}" title="${ma({hass:this.hass,string:"extra_states.timed_preset_title"})}"
> >
<option value="" ?selected=${!this.timedPresetDuration}>--</option> <option value="" ?selected=${!this.timedPresetDuration}>--</option>
<option value="15" ?selected=${15===this.timedPresetDuration}>15 ${_n({hass:this.hass,string:"extra_states.minutes"})}</option> <option value="15" ?selected=${15===this.timedPresetDuration}>15 ${ma({hass:this.hass,string:"extra_states.minutes"})}</option>
<option value="30" ?selected=${30===this.timedPresetDuration}>30 ${_n({hass:this.hass,string:"extra_states.minutes"})}</option> <option value="30" ?selected=${30===this.timedPresetDuration}>30 ${ma({hass:this.hass,string:"extra_states.minutes"})}</option>
<option value="60" ?selected=${60===this.timedPresetDuration}>1 h</option> <option value="60" ?selected=${60===this.timedPresetDuration}>1 h</option>
<option value="120" ?selected=${120===this.timedPresetDuration}>2 h</option> <option value="120" ?selected=${120===this.timedPresetDuration}>2 h</option>
<option value="240" ?selected=${240===this.timedPresetDuration}>4 h</option> <option value="240" ?selected=${240===this.timedPresetDuration}>4 h</option>
@@ -1553,28 +1561,28 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
`} `}
<div id="left-infos" class="${(null===(x=this._config)||void 0===x?void 0:x.disable_presets)?"no-presets":""}"> <div id="left-infos" class="${(null===(x=this._config)||void 0===x?void 0:x.disable_presets)?"no-presets":""}">
${this.isRecalculateScheduled?j` ${this.isRecalculateScheduled?B`
${this._renderRecalculateScheduledButton()} ${this._renderRecalculateScheduledButton()}
`:""} `:""}
${this.messages.length>0?j` ${this.messages.length>0?B`
${this._renderMessagesButton()} ${this._renderMessagesButton()}
`:""} `:""}
${this._config.autoStartStopEnableEntity&&this._isAutoStartStopConfigured?j` ${(this._config.autoStartStopEnableEntity||this._config.autoStartStopStopModeEntity)&&this._isAutoStartStopConfigured?B`
${this._renderAutoStartStopEnable()} ${this._renderAutoStartStopEnable()}
`:""} `:""}
${j` ${B`
${this._externalPowerInfos.map((t=>this._renderPowerInfo(t)))} ${this._externalPowerInfos.map((t=>this._renderPowerInfo(t)))}
`} `}
${j` ${B`
${this.powerInfos.map((t=>this._renderPowerInfo(t)))} ${this.powerInfos.map((t=>this._renderPowerInfo(t)))}
`} `}
${j` ${B`
${this.autoFanInfos.map((t=>this._renderAutoFanInfo(t)))} ${this.autoFanInfos.map((t=>this._renderAutoFanInfo(t)))}
`} `}
</div> </div>
<div id="right-lock"> <div id="right-lock">
${(null===(k=this._config)||void 0===k?void 0:k.allow_lock_toggle)?B` ${(null===(k=this._config)||void 0===k?void 0:k.allow_lock_toggle)?W`
<ha-icon-button <ha-icon-button
class="lock-icon ${this._isLocked?"locked":"unlocked"}" class="lock-icon ${this._isLocked?"locked":"unlocked"}"
.path=${this._isLocked?Pt:Et} .path=${this._isLocked?Pt:Et}
@@ -1587,11 +1595,11 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
${this._renderPresetModificationPanel()} ${this._renderPresetModificationPanel()}
${this._renderRegulationChartPanel()} ${this._renderRegulationChartPanel()}
</div> </div>
`;return this._renderingAsClassic=!1,M}_applyTheme(t){this._config||(this._config={}),this._config.theme=t,Tn(this,"config-changed",{config:this._config}),this._closeThemeMenu(),this.setAttribute("theme",t),this._applyThemeOverrides(t)}async _menuLockToggle(){var t;if((null===(t=this._config)||void 0===t?void 0:t.entity)&&this.hass&&this.stateObj){if(this._hasLockCode)return this.isLocking=!this._isLocked,this.showDigicodeModal=!0,void(this.enteredCode="");try{this._isLocked?this._isLockConfigured?await this.hass.callService("versatile_thermostat","unlock",{entity_id:this._config.entity}):(this._isLocked=this.isUserLocked=!1,this.requestUpdate()):this._isLockConfigured?await this.hass.callService("versatile_thermostat","lock",{entity_id:this._config.entity}):(this._isLocked=this.isUserLocked=!0,this.requestUpdate())}catch(t){console.error(t)}}}_menuCancelTimedPreset(){this.timedPresetActive&&this._handleCancelTimedPreset()}firstUpdated(t){this._init=!1}shouldUpdate(t){return void 0!==t.has("_config")&&void 0!==t.get("_config")&&(this._hasOverpowering=!1,this._hasWindow=!1,this._hasWindowByPass=!1,this._hasMotion=!1,this._hasPresence=!1,this._hasAutoStartStop=!1,this._isAutoStartStopEnabled=!1,this.humidity=0),void 0!==t.get("hass")&&(this._init=!1),!0}updated(t){var e,i,o;super.updated(t),this._firstRender=!1,"gunmalmg"!==(null===(e=this._config)||void 0===e?void 0:e.theme)||this._gunmalmgPresetScrollDone||requestAnimationFrame((()=>{var t;const e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector(".gunmalmg-presets-scroll"),i=null==e?void 0:e.querySelector(".selected-icon");if(i&&e){this._gunmalmgPresetScrollDone=!0;const t=i.closest(".preset-label")||i,o=t.offsetLeft,n=t.offsetWidth,a=e.clientWidth,s=n,r=Math.max(0,o-(a-n)/2+s);e.scrollLeft=r}})),t.has("showDigicodeModal")&&(this.showDigicodeModal?window.addEventListener("keydown",this._handleKeyDown):window.removeEventListener("keydown",this._handleKeyDown)),null===(o=null===(i=null==this?void 0:this.shadowRoot)||void 0===i?void 0:i.querySelector(".security"))||void 0===o||o.addEventListener("click",(()=>{var t,e,i,o;null===(e=null===(t=null==this?void 0:this.shadowRoot)||void 0===t?void 0:t.querySelector(".security"))||void 0===e||e.remove(),null===(o=null===(i=null==this?void 0:this.shadowRoot)||void 0===i?void 0:i.querySelector(".content"))||void 0===o||o.classList.remove("security_msg"),this._vibrate(2)}))}_willUpdatePower(){let t,e,i;this._externalPowerInfos=[],this._config.powerEntity&&(console.log(`There is a powerEntity ${this._config.powerEntity}`),t=this.hass.states[this._config.powerEntity],e=Number(t.state),i=t.attributes.unit_of_measurement,console.log(`Power found ${e} ${i} for ${name}`)),e&&(console.log("J'ai pushé du power"),this._externalPowerInfos.push({name:"mean_power_cycle",value:e,unit:i,class:"vt-power-color"}))}_classifyPresetEntity(t){const e=t.toLowerCase(),i=/_cool_/.test(e)||e.endsWith("_cool")||/_ac_(away_)?temp$/.test(e),o=e.includes("_away");let n=null;return e.includes("frost")||e.includes("hors_gel")?n="frost":e.includes("eco")?n="eco":e.includes("comfort")?n="comfort":e.includes("boost")&&(n="boost"),n?{entityId:t,preset:n,mode:i?"cool":"heat",away:o}:null}_discoverPresetTempEntities(){var t,e;if(!this.hass||!(null===(t=this._config)||void 0===t?void 0:t.entity))return;const i=this.hass.entities;if(!i)return void console.log("[PresetMod] hass.entities not available");const o=i[this._config.entity];if(!(null==o?void 0:o.device_id))return void console.log(`[PresetMod] No device_id for entity ${this._config.entity}`);const n=o.device_id;console.log(`[PresetMod] device_id=${n}`);const a=[];for(const[t,o]of Object.entries(i)){if(o.device_id!==n)continue;if(!t.startsWith("number."))continue;const i=this.hass.states[t];if(!i)continue;if("temperature"!==(null===(e=i.attributes)||void 0===e?void 0:e.device_class))continue;const s=this._classifyPresetEntity(t);s&&(console.log(`[PresetMod] found entity: ${t} preset=${s.preset} mode=${s.mode} away=${s.away}`),a.push(s))}const s=this._presetTempEntities.map((t=>t.entityId)).join(","),r=a.map((t=>t.entityId)).join(",");s!==r&&(this._presetTempEntities=a)}willUpdate(t){var e,i,o,n,a,s,r,l,c,d,h,u,m,p,_,g,f,b,v,y,w,x,k,T,S,M,D,C,A,P,E,L,$,z,O,V,H,R,I,N,F,W,B,j,U,Y,q,Z,X,K,G,Q,J;if(!this.hass||!this._config||!t.has("hass")&&!t.has("_config"))return;const tt=this._config.entity;this._willUpdatePower(),(null===(e=this._config)||void 0===e?void 0:e.allow_preset_modification)&&this._discoverPresetTempEntities();const et=this.hass.states[tt];if(!et)return void console.log("No state");const it=t.get("hass");if(!it||it.states[tt]!==et){if(!this._config||!this.hass||!this._config.entity)return void console.log("No change return");console.log("Something may have change"),this.stateObj=et;const t=this.stateObj.attributes,e=this.stateObj.state;this._isLockConfigured=!0===(null==t?void 0:t.is_lock_configured),(null==t?void 0:t.lock_manager)&&(this._isLocked=(null===(i=null==t?void 0 Line truncated `;return this._renderingAsClassic=!1,M}_applyTheme(t){this._config||(this._config={}),this._config.theme=t,ka(this,"config-changed",{config:this._config}),this._closeThemeMenu(),this.setAttribute("theme",t),this._applyThemeOverrides(t)}async _menuLockToggle(){var t;if((null===(t=this._config)||void 0===t?void 0:t.entity)&&this.hass&&this.stateObj){if(this._hasLockCode)return this.isLocking=!this._isLocked,this.showDigicodeModal=!0,void(this.enteredCode="");try{this._isLocked?this._isLockConfigured?await this.hass.callService("versatile_thermostat","unlock",{entity_id:this._config.entity}):(this._isLocked=this.isUserLocked=!1,this.requestUpdate()):this._isLockConfigured?await this.hass.callService("versatile_thermostat","lock",{entity_id:this._config.entity}):(this._isLocked=this.isUserLocked=!0,this.requestUpdate())}catch(t){console.error(t)}}}_menuCancelTimedPreset(){this.timedPresetActive&&this._handleCancelTimedPreset()}firstUpdated(t){this._init=!1}shouldUpdate(t){return void 0!==t.has("_config")&&void 0!==t.get("_config")&&(this._hasOverpowering=!1,this._hasWindow=!1,this._hasWindowByPass=!1,this._hasMotion=!1,this._hasPresence=!1,this._hasAutoStartStop=!1,this._isAutoStartStopEnabled=!1,this._autoStartStopStopMode=xr,this._autoStartStopStopModeOptions=[],this.humidity=0),void 0!==t.get("hass")&&(this._init=!1),!0}updated(t){var e,i,o;super.updated(t),this._firstRender=!1,"gunmalmg"!==(null===(e=this._config)||void 0===e?void 0:e.theme)||this._gunmalmgPresetScrollDone||requestAnimationFrame((()=>{var t;const e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector(".gunmalmg-presets-scroll"),i=null==e?void 0:e.querySelector(".selected-icon");if(i&&e){this._gunmalmgPresetScrollDone=!0;const t=i.closest(".preset-label")||i,o=t.offsetLeft,a=t.offsetWidth,n=e.clientWidth,s=a,r=Math.max(0,o-(n-a)/2+s);e.scrollLeft=r}})),t.has("showDigicodeModal")&&(this.showDigicodeModal?window.addEventListener("keydown",this._handleKeyDown):window.removeEventListener("keydown",this._handleKeyDown)),null===(o=null===(i=null==this?void 0:this.shadowRoot)||void 0===i?void 0:i.querySelector(".security"))||void 0===o||o.addEventListener("click",(()=>{var t,e,i,o;null===(e=null===(t=null==this?void 0:this.shadowRoot)||void 0===t?void 0:t.querySelector(".security"))||void 0===e||e.remove(),null===(o=null===(i=null==this?void 0:this.shadowRoot)||void 0===i?void 0:i.querySelector(".content"))||void 0===o||o.classList.remove("security_msg"),this._vibrate(2)}))}_willUpdatePower(){let t,e,i;this._externalPowerInfos=[],this._config.powerEntity&&(console.log(`There is a powerEntity ${this._config.powerEntity}`),t=this.hass.states[this._config.powerEntity],e=Number(t.state),i=t.attributes.unit_of_measurement,console.log(`Power found ${e} ${i} for ${name}`)),e&&(console.log("J'ai pushé du power"),this._externalPowerInfos.push({name:"mean_power_cycle",value:e,unit:i,class:"vt-power-color"}))}_classifyPresetEntity(t){const e=t.toLowerCase(),i=/_cool_/.test(e)||e.endsWith("_cool")||/_ac_(away_)?temp$/.test(e),o=e.includes("_away");let a=null;return e.includes("frost")||e.includes("hors_gel")?a="frost":e.includes("eco")?a="eco":e.includes("comfort")?a="comfort":e.includes("boost")&&(a="boost"),a?{entityId:t,preset:a,mode:i?"cool":"heat",away:o}:null}_discoverPresetTempEntities(){var t,e;if(!this.hass||!(null===(t=this._config)||void 0===t?void 0:t.entity))return;const i=this.hass.entities;if(!i)return void console.log("[PresetMod] hass.entities not available");const o=i[this._config.entity];if(!(null==o?void 0:o.device_id))return void console.log(`[PresetMod] No device_id for entity ${this._config.entity}`);const a=o.device_id;console.log(`[PresetMod] device_id=${a}`);const n=[];for(const[t,o]of Object.entries(i)){if(o.device_id!==a)continue;if(!t.startsWith("number."))continue;const i=this.hass.states[t];if(!i)continue;if("temperature"!==(null===(e=i.attributes)||void 0===e?void 0:e.device_class))continue;const s=this._classifyPresetEntity(t);s&&(console.log(`[PresetMod] found entity: ${t} preset=${s.preset} mode=${s.mode} away=${s.away}`),n.push(s))}const s=this._presetTempEntities.map((t=>t.entityId)).join(","),r=n.map((t=>t.entityId)).join(",");s!==r&&(this._presetTempEntities=n)}willUpdate(t){var e,i,o,a,n,s,r,l,c,d,h,u,p,m,_,f,g,b,v,y,w,x,k,S,T,M,D,C,A,P,E,L,$,z,O,V,H,I,R,F,N,j,W,B,U,Y,q,Z,X,K,G,Q,J,tt,et,it,ot,at,nt,st;if(!this.hass||!this._config||!t.has("hass")&&!t.has("_config"))return;const rt=this._config.entity;this._willUpdatePower(),(null===(e=this._config)||void 0===e?void 0:e.allow_preset_modification)&&this._discoverPresetTempEntities();const lt=this.hass.states[rt];if(!lt)return void console.log("No state");const ct=t.get("hass"),dt=null===(i=this._config)||void 0===i?void 0:i.autoFanEnableEntity,ht=!(!dt||ct&&ct.states[dt]===this.hass.states[dt]);if(!ct||ct.states[rt]!==lt||ht){if(!this._config||!this.hass||!this._config.entity)return void console.log("No change return");console.log("Something may have change" Line truncated
<text class="hvac-action-text-svg ${this.hvacAction}" x="${t}" y="${e}" dominant-baseline="middle" text-anchor="middle"> <text class="hvac-action-text-svg ${this.hvacAction}" x="${t}" y="${e}" dominant-baseline="middle" text-anchor="middle">
${o} ${o}
</text> </text>
`}_renderHVACAction(){return this.hvacAction&&"off"!==this.hvacAction&&"idle"!==this.hvacAction?"heating"===this.hvacAction?j`<path class="status ${this.isDeviceActive?"active":""}" transform="translate(5,-4) scale(0.25)" fill="#9d9d9d" d="${Dt}" />`:"cooling"===this.hvacAction||"cool"==this.hvacMode?j`<path class="status cooler ${this.isDeviceActive?"active":""}" transform="translate(5,-4) scale(0.25)" fill="#9d9d9d" d="${vt}" />`:j`<path class="status" transform="translate(5,-4) scale(0.25)" fill="#9d9d9d" d="${kt}" />`:B``}_renderHVACActionBadge(){return this.hvacAction&&"off"!==this.hvacAction&&"idle"!==this.hvacAction?"heating"===this.hvacAction?j`<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${Dt}"/></svg>`:"cooling"===this.hvacAction?j`<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${vt}"/></svg>`:j`<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${yt}"/></svg>`:B``}_renderIcon(t,e,i){if(!cr[t])return B``;const o=this.hass.localize(`component.climate.state._.${t}`)||_n({hass:this.hass,string:`extra_states.${t}`});return B` `}_renderHVACAction(){return this.hvacAction&&"off"!==this.hvacAction&&"idle"!==this.hvacAction?"heating"===this.hvacAction?B`<path class="status ${this.isDeviceActive?"active":""}" transform="translate(5,-4) scale(0.25)" fill="#9d9d9d" d="${Dt}" />`:"cooling"===this.hvacAction||"cool"==this.hvacMode?B`<path class="status cooler ${this.isDeviceActive?"active":""}" transform="translate(5,-4) scale(0.25)" fill="#9d9d9d" d="${vt}" />`:B`<path class="status" transform="translate(5,-4) scale(0.25)" fill="#9d9d9d" d="${kt}" />`:W``}_renderHVACActionBadge(){return this.hvacAction&&"off"!==this.hvacAction&&"idle"!==this.hvacAction?"heating"===this.hvacAction?B`<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${Dt}"/></svg>`:"cooling"===this.hvacAction?B`<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${vt}"/></svg>`:B`<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${yt}"/></svg>`:W``}_renderIcon(t,e,i){if(!dr[t])return W``;const o=this.hass.localize(`component.climate.state._.${t}`)||ma({hass:this.hass,string:`extra_states.${t}`});return W`
<div class="hvac-badge-container"> <div class="hvac-badge-container">
<ha-icon-button <ha-icon-button
title="${e===t?t:""}" title="${e===t?t:""}"
@@ -1599,12 +1607,12 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
.mode=${t} .mode=${t}
@click=${i?this._cycleHvacMode:this._handleAction} @click=${i?this._cycleHvacMode:this._handleAction}
tabindex="0" tabindex="0"
.path=${cr[t]} .path=${dr[t]}
.label=${o} .label=${o}
></ha-icon-button> ></ha-icon-button>
${(()=>{if(this.theme!==vr||this._renderingAsClassic)return B``;let t="";return this.hvacAction&&"off"!==this.hvacAction&&"idle"!==this.hvacAction?(t="heating"===this.hvacAction?"heating":"cooling"===this.hvacAction?"cooling":"warning",B`<div class="hvac-badge ${t}">${this._renderHVACActionBadge()}</div>`):B``})()} ${(()=>{if(this.theme!==Tr||this._renderingAsClassic)return W``;let t="";return this.hvacAction&&"off"!==this.hvacAction&&"idle"!==this.hvacAction?(t="heating"===this.hvacAction?"heating":"cooling"===this.hvacAction?"cooling":"warning",W`<div class="hvac-badge ${t}">${this._renderHVACActionBadge()}</div>`):W``})()}
</div> </div>
`}async _cycleHvacMode(){var t;if(!(null===(t=this._config)||void 0===t?void 0:t.entity)||!this.hass)return;const e=Array.isArray(this.modes)&&this.modes.length>0?this.modes:[];if(0===e.length)return;const i=this.hvacMode||"";let o=e.indexOf(i);-1===o&&(o=0);const n=e[(o+1)%e.length];try{n===ur?await this.hass.callService("versatile_thermostat","set_hvac_mode_sleep",{entity_id:this._config.entity}):await this.hass.callService("climate","set_hvac_mode",{entity_id:this._config.entity,hvac_mode:n})}catch(t){console.error(t)}}_renderMessagesButton(){const t=_n({hass:this.hass,string:"extra_states.messages-button"});return B` `}async _cycleHvacMode(){var t;if(!(null===(t=this._config)||void 0===t?void 0:t.entity)||!this.hass)return;const e=Array.isArray(this.modes)&&this.modes.length>0?this.modes:[];if(0===e.length)return;const i=this.hvacMode||"";let o=e.indexOf(i);-1===o&&(o=0);const a=e[(o+1)%e.length];try{a===mr?await this.hass.callService("versatile_thermostat","set_hvac_mode_sleep",{entity_id:this._config.entity}):await this.hass.callService("climate","set_hvac_mode",{entity_id:this._config.entity,hvac_mode:a})}catch(t){console.error(t)}}_renderMessagesButton(){const t=ma({hass:this.hass,string:"extra_states.messages-button"});return W`
<ha-icon-button <ha-icon-button
title="${t}" title="${t}"
class="messages-button ${this._hasError?"error":""}" class="messages-button ${this._hasError?"error":""}"
@@ -1614,7 +1622,7 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
.label=${t} .label=${t}
> >
</ha-icon-button> </ha-icon-button>
`}_renderRecalculateScheduledButton(){const t=_n({hass:this.hass,string:"extra_states.recalculation_scheduled"});return B` `}_renderRecalculateScheduledButton(){const t=ma({hass:this.hass,string:"extra_states.recalculation_scheduled"});return W`
<ha-icon-button <ha-icon-button
title="${t}" title="${t}"
class="messages-button" class="messages-button"
@@ -1623,30 +1631,30 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
.label=${t} .label=${t}
> >
</ha-icon-button> </ha-icon-button>
`}_renderWindowByPassButton(){const t=_n({hass:this.hass,string:"extra_states.window-bypass-button"});return B` `}_renderWindowByPassButton(){const t=ma({hass:this.hass,string:"extra_states.window-bypass-button"});return W`
<ha-icon-button <ha-icon-button
title="${t}" title="${t}"
class="window-bypass-button" class="window-bypass-button"
@click=${this._handleToggleWindowByPass} @click=${this._handleToggleWindowByPass}
tabindex="0" tabindex="0"
.path=${Rt} .path=${It}
.label=${t} .label=${t}
> >
</ha-icon-button> </ha-icon-button>
`}_renderPreset(t,e){const i=(this.hass.localize(`component.climate.state._.${t}`)||_n({hass:this.hass,string:`extra_states.${t}`}))+"\n"+_n({hass:this.hass,string:"extra_states.change_message"});return B` `}_getPresetTemperature(t,e,i,o=!0){var a,n,s;if(!this.hass)return null;const r=null!=e?e:this.hvacMode===pr?"cool":"heat",l=null!=i?i:!!this._hasPresence&&!this.presence;if(o&&(null===(a=this._presetTempEntities)||void 0===a?void 0:a.length)){const e=this._presetTempEntities.filter((e=>e.preset===t));if(e.length>0){const i=[...e.filter((t=>t.mode===r&&t.away===l)),...e.filter((t=>t.mode===r&&t.away!==l)),...e.filter((t=>t.mode!==r))];for(const e of i){const i=this.hass.states[e.entityId];if(i&&i.state!==cr){const o=Number.parseFloat(i.state);if(Number.isFinite(o)&&0!==o)return console.log(`[PresetTemp] entity value for ${t} from ${e.entityId}: ${o}`),o}}}}const c=null===(s=null===(n=this.stateObj)||void 0===n?void 0:n.attributes)||void 0===s?void 0:s.preset_temperatures;if(!c||"object"!=typeof c)return null;const d=[],h=`${t}_${r}_temp`,u=`${t}_${r}_away_temp`;l&&d.push(u),d.push(h,`${t}_away_temp`,`${t}_temp`,t);for(const e of d)if(e in c&&void 0!==c[e]){const i=Number.parseFloat(String(c[e]));if(Number.isFinite(i)&&0!==i)return console.log(`[PresetTemp] central value for ${t} using key ${e}: ${i}`),i}if(c[r]&&"object"==typeof c[r]){const e=c[r];if(void 0!==e[t]){const i=Number.parseFloat(String(e[t]));if(Number.isFinite(i)&&0!==i)return console.log(`[PresetTemp] central nested value for ${t} in ${r}: ${i}`),i}}return null}_hasValidCentralPresetTemperatures(){var t,e;if(!(null===(e=null===(t=this.stateObj)||void 0===t?void 0:t.attributes)||void 0===e?void 0:e.preset_temperatures))return!1;const i=this.stateObj.attributes.preset_temperatures,o=t=>"number"==typeof t?Number.isFinite(t)&&0!==t:!(!t||"object"!=typeof t)&&Object.values(t).some(o);return o(i)}_renderPreset(t,e){const i=this.hass.localize(`component.climate.state._.${t}`)||ma({hass:this.hass,string:`extra_states.${t}`}),o=this._getPresetTemperature(t),a=null!==o?`${Ta(o,this.hass.locale,{minimumFractionDigits:1,maximumFractionDigits:1})} ${this.hass.config.unit_system.temperature}`:null,n=a?`${i} - ${a}`:i,s=`${n}\n${ma({hass:this.hass,string:"extra_states.change_message"})}`;return W`
<div class="preset-label preset-${t}"> <div class="preset-label preset-${t}">
<ha-icon-button <ha-icon-button
title="${e===t?t:""}" title="${n}"
class=${bt({"selected-icon":e===t})} class=${bt({"selected-icon":e===t})}
.preset=${t} .preset=${t}
@click=${this._handlePreset} @click=${this._handlePreset}
tabindex="0" tabindex="0"
.path=${cr[t]} .path=${dr[t]}
.label=${i} .label=${s}
> >
</ha-icon-button> </ha-icon-button>
</div> </div>
`}_renderPowerInfo(t){const e=this.hass.localize(`component.climate.state._.${t.name}`)||_n({hass:this.hass,string:`extra_states.${t.name}`});return B` `}_renderPowerInfo(t){const e=this.hass.localize(`component.climate.state._.${t.name}`)||ma({hass:this.hass,string:`extra_states.${t.name}`});return W`
<div class="left-info-label"> <div class="left-info-label">
<span> <span>
<ha-icon-button <ha-icon-button
@@ -1654,14 +1662,14 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
class=${t.class} class=${t.class}
.name=${t.name} .name=${t.name}
tabindex="0" tabindex="0"
.path=${cr[t.name]} .path=${dr[t.name]}
.label=${e} .label=${e}
> >
</ha-icon-button> </ha-icon-button>
</span> </span>
<span>${t.value} ${t.unit}</span> <span>${t.value} ${t.unit}</span>
</div> </div>
`}_renderAutoFanInfo(t){const e=(this.hass.localize(`component.climate.state._.${t.name}`)||_n({hass:this.hass,string:`extra_states.${t.name}`}))+"\n"+_n({hass:this.hass,string:"extra_states.toggle_message"});return B` `}_renderAutoFanInfo(t){const e=(this.hass.localize(`component.climate.state._.${t.name}`)||ma({hass:this.hass,string:`extra_states.${t.name}`}))+"\n"+ma({hass:this.hass,string:"extra_states.toggle_message"});return W`
<div class="left-info-label"> <div class="left-info-label">
<span> <span>
<ha-icon-button <ha-icon-button
@@ -1670,22 +1678,49 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
.name=${t.name} .name=${t.name}
@click=${this._handleClickAutoFanInfo} @click=${this._handleClickAutoFanInfo}
tabindex="0" tabindex="0"
.path=${cr[t.name]} .path=${dr[t.name]}
.label=${e} .label=${e}
> >
</ha-icon-button> </ha-icon-button>
</span> </span>
<span>${t.value} ${t.unit}</span> <span class="clickable-info-label" @click=${this._handleClickAutoFanInfo}>${t.value} ${t.unit}</span>
</div> </div>
`}_renderAutoStartStopEnable(){const t=_n({hass:this.hass,string:"extra_states.auto_start_stop_enable"}),e=_n({hass:this.hass,string:"extra_states.auto_start_stop_label"}),i=this._isAutoStartStopEnabled?"checked":"";return console.log(`checked=${i}`),B` `}_renderAutoStartStopEnable(){const t=ma({hass:this.hass,string:"extra_states.auto_start_stop_enable"}),e=ma({hass:this.hass,string:"extra_states.auto_start_stop_label"}),i=this._isAutoStartStopEnabled?this._autoStartStopStopMode:wr,o=this._autoStartStopStopModeOptions.length?this._autoStartStopStopModeOptions:[xr],a=[wr,...o],n=ma({hass:this.hass,string:`extra_states.auto_start_stop_mode_${i}`});return W`
<div class="left-info-label" title="${t}"> <div class="left-info-label" title="${e}">
<span> <span>
<input type="checkbox" .checked=${this._isAutoStartStopEnabled} class="auto-start-stop-enable" @click=${this._handleClickAutoStartStopEnable} .label="${t}" name="auto-start-stop-enable"> <ha-icon-button
title="${e}"
class="auto-start-stop"
.name=${"auto_start_stop"}
@click=${this._handleClickAutoStartStopIcon}
tabindex="0"
.path=${dr.auto_start_stop}
.label=${e}
>
</ha-icon-button>
</span> </span>
<span>${e}</span> ${this._autoStartStopEditMode&&!this.isUserLocked?W`
<span>
<select
class="auto-start-stop-select ${this._isAutoStartStopEnabled?"active":""}"
@change=${this._handleChangeAutoStartStop}
@blur=${this._handleBlurAutoStartStop}
title="${t}"
name="auto-start-stop-select"
>
${a.map((t=>W`
<option value="${t}" ?selected=${i===t}>
${ma({hass:this.hass,string:`extra_states.auto_start_stop_mode_${t}`})}
</option>
`))}
</select>
</span>
`:W`
<span class="clickable-info-label" @click=${this._handleClickAutoStartStopIcon}>${n}</span>
`}
</div> </div>
`}_handleMoreInfo(){Tn(this,"hass-more-info",{entityId:this._config.entity})}_handleLockToggle(){var t,e;if((null===(t=this._config)||void 0===t?void 0:t.allow_lock_toggle)&&(null===(e=this._config)||void 0===e?void 0:e.entity)&&this.hass&&this.stateObj)if(this._isLocked){if(this._hasLockCode)return this.isLocking=!1,this.showDigicodeModal=!0,void(this.enteredCode="");this._isLockConfigured?this.hass.callService("versatile_thermostat","unlock",{entity_id:this._config.entity}):(this._isLocked=this.isUserLocked=!1,this.requestUpdate())}else{if(this._hasLockCode)return this.isLocking=!0,this.showDigicodeModal=!0,void(this.enteredCode="");this._isLockConfigured?this.hass.callService("versatile_thermostat","lock",{entity_id:this._config.entity}):(this._isLocked=this.isUserLocked=!0,this.requestUpdate())}}_handleKeypadPress(t){this.enteredCode.length<4&&(this.enteredCode+=t,this.codeError=!1,4===this.enteredCode.length&&this._handleValidate())}_handleKeypadClear(){this.enteredCode=this.enteredCode.slice(0,-1),this.codeError=!1}_handleModalClose(){this.showDigicodeModal=!1,this.enteredCode="",this.codeError=!1}async _handleValidate(){if(4===this.enteredCode.length){const t=this.isLocking?"lock":"unlock";try{await this.hass.callService("versatile_thermostat",t,{entity_id:this._config.entity,code:this.enteredCode}),this._handleModalClose()}catch(t){this.codeError=!0,this.enteredCode="",this._vibrate(200)}}else this.codeError=!0,this.enteredCode="",this._vibrate(200)}buildTitle(){var t,e,i;let o="";return this._hasWindow&&!(null===(t=this._config)||void 0===t?void 0:t.disable_window)&&(o+=_n({hass:this.hass,string:"extra_states.window_open"})+"\n"),this._hasWindowByPass&&(o+=_n({hass:this.hass,string:"extra_states.window_bypass"})+"\n"),this._hasOverpowering&&!(null===(e=this._config)||void 0===e?void 0:e.disable_overpowering)&&(o+=_n({hass:this.hass,string:"extra_states.overpowering"})+"\n"),this._hasPresence&&(o+=_n({hass:this.hass,string:"extra_states.presence"})+"\n"),this._hasAutoStartStop&&!(null===(i=this._config)||void 0===i?void 0:i.disable_autoStartStop)&&(o+=_n({hass:this.hass,string:"extra_states.auto_start_stop"})+"\n"),this._hasMotion&&(o+=_n({hass:this.hass,string:"extra_states.motion"})+"\n"),o}_renderTemperature(t,e,i,o,n){var a;let s=76,r=56,l=.2;const c=e?-2:-1,d=e?-5.5:-2;let h;h=t?Mn(t,this.hass.locale,{minimumFractionDigits:1,maximumFractionDigits:1}):this.hass.localize("extra_states.temp_unavailable"),n&&e&&(s=this.effectiveDisableCircle?30:35,r=56,l=.25);const u=e?"temp-main":"temp-secondary";return j` `}_handleClickAutoStartStopIcon(){this.isUserLocked||(this._autoStartStopEditMode=!this._autoStartStopEditMode)}_handleBlurAutoStartStop(){this._autoStartStopEditMode=!1}_handleMoreInfo(){ka(this,"hass-more-info",{entityId:this._config.entity})}_handleLockToggle(){var t,e;if((null===(t=this._config)||void 0===t?void 0:t.allow_lock_toggle)&&(null===(e=this._config)||void 0===e?void 0:e.entity)&&this.hass&&this.stateObj)if(this._isLocked){if(this._hasLockCode)return this.isLocking=!1,this.showDigicodeModal=!0,void(this.enteredCode="");this._isLockConfigured?this.hass.callService("versatile_thermostat","unlock",{entity_id:this._config.entity}):(this._isLocked=this.isUserLocked=!1,this.requestUpdate())}else{if(this._hasLockCode)return this.isLocking=!0,this.showDigicodeModal=!0,void(this.enteredCode="");this._isLockConfigured?this.hass.callService("versatile_thermostat","lock",{entity_id:this._config.entity}):(this._isLocked=this.isUserLocked=!0,this.requestUpdate())}}_handleKeypadPress(t){this.enteredCode.length<4&&(this.enteredCode+=t,this.codeError=!1,4===this.enteredCode.length&&this._handleValidate())}_handleKeypadClear(){this.enteredCode=this.enteredCode.slice(0,-1),this.codeError=!1}_handleModalClose(){this.showDigicodeModal=!1,this.enteredCode="",this.codeError=!1}async _handleValidate(){if(4===this.enteredCode.length){const t=this.isLocking?"lock":"unlock";try{await this.hass.callService("versatile_thermostat",t,{entity_id:this._config.entity,code:this.enteredCode}),this._handleModalClose()}catch(t){this.codeError=!0,this.enteredCode="",this._vibrate(200)}}else this.codeError=!0,this.enteredCode="",this._vibrate(200)}buildTitle(){var t,e,i;let o="";return this._hasWindow&&!(null===(t=this._config)||void 0===t?void 0:t.disable_window)&&(o+=ma({hass:this.hass,string:"extra_states.window_open"})+"\n"),this._hasWindowByPass&&(o+=ma({hass:this.hass,string:"extra_states.window_bypass"})+"\n"),this._hasOverpowering&&!(null===(e=this._config)||void 0===e?void 0:e.disable_overpowering)&&(o+=ma({hass:this.hass,string:"extra_states.overpowering"})+"\n"),this._hasPresence&&(o+=ma({hass:this.hass,string:"extra_states.presence"})+"\n"),this._hasAutoStartStop&&!(null===(i=this._config)||void 0===i?void 0:i.disable_autoStartStop)&&(o+=ma({hass:this.hass,string:"extra_states.auto_start_stop"})+"\n"),this._hasMotion&&(o+=ma({hass:this.hass,string:"extra_states.motion"})+"\n"),o}_renderTemperature(t,e,i,o,a){var n;let s=76,r=56,l=.2;const c=e?-2:-1,d=e?-5.5:-2;let h;h=t?Ta(t,this.hass.locale,{minimumFractionDigits:1,maximumFractionDigits:1}):this.hass.localize("extra_states.temp_unavailable"),a&&e&&(s=this.effectiveDisableCircle?30:35,r=56,l=.25);const u=e?"temp-main":"temp-secondary";return B`
${n&&!(null===(a=this._config)||void 0===a?void 0:a.disable_target_icon)?j` ${a&&!(null===(n=this._config)||void 0===n?void 0:n.disable_target_icon)?B`
<path <path
class="target-icon" class="target-icon"
transform="translate(${s}, ${r}) scale(${l})" transform="translate(${s}, ${r}) scale(${l})"
@@ -1693,46 +1728,46 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
d="${"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,10.84 21.79,9.69 21.39,8.61L19.79,10.21C19.93,10.8 20,11.4 20,12A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4C12.6,4 13.2,4.07 13.79,4.21L15.4,2.6C14.31,2.21 13.16,2 12,2M19,2L15,6V7.5L12.45,10.05C12.3,10 12.15,10 12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12C14,11.85 14,11.7 13.95,11.55L16.5,9H18L22,5H19V2M12,6A6,6 0 0,0 6,12A6,6 0 0,0 12,18A6,6 0 0,0 18,12H16A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8V6Z"}" d="${"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,10.84 21.79,9.69 21.39,8.61L19.79,10.21C19.93,10.8 20,11.4 20,12A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4C12.6,4 13.2,4.07 13.79,4.21L15.4,2.6C14.31,2.21 13.16,2 12,2M19,2L15,6V7.5L12.45,10.05C12.3,10 12.15,10 12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12C14,11.85 14,11.7 13.95,11.55L16.5,9H18L22,5H19V2M12,6A6,6 0 0,0 6,12A6,6 0 0,0 12,18A6,6 0 0,0 18,12H16A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8V6Z"}"
/>`:""} />`:""}
<text class="main-value ${u}" x="${i}" y="${o}" dominant-baseline="middle" text-anchor="middle"> <text class="main-value ${u}" x="${i}" y="${o}" dominant-baseline="middle" text-anchor="middle">
${j`${h}`} ${B`${h}`}
<tspan class="uom" dx="${c}" dy="${d}"> <tspan class="uom" dx="${c}" dy="${d}">
${j` ${B`
${this.hass.config.unit_system.temperature} ${this.hass.config.unit_system.temperature}
`} `}
</tspan> </tspan>
</text> </text>
`}constructor(){super(),this.value={},this._selectTargetTemperature="low",this.current=0,this.humidity=0,this.temperature=0,this.min=7,this.max=35,this.step=.5,this.powerPercent=0,this.meanCyclePower=0,this.valveOpenPercent=0,this.devicePower=0,this.regulatedTargetTemperature=null,this.isOn=!1,this.window=!1,this.windowByPass=!1,this.presence=!1,this.motion=!1,this.overpowering=!1,this.isDeviceActive=!1,this.isSleeping=!1,this.isRegulated=!1,this.isRecalculateScheduled=!1,this.windowState="off",this.windowAutoState="off",this.overpoweringState="off",this.presenceState="off",this.motionState="off",this.safetyState="off",this.status="loading",this.hvacMode=hr,this.hvacAction="idle",this.preset=dr,this.autoRegulationMode="",this.currentAutoFanMode=mr,this.autoFanMode=mr,this.fanMode="",this.hvacOffReason="",this.dragging=!1,this.name="",this.target="value",this._debouncedCallService=((t,e,i=!1)=>{let o;const n=(...n)=>{const a=i&&!o;clearTimeout(o),o=window.setTimeout((()=>{o=void 0,i||t(...n)}),e),a&&t(...n)};return n.cancel=()=>{clearTimeout(o)},n})((t=>this._callService(t)),1e3),this._init=!0,this._firstRender=!0,this._gunmalmgPresetScrollDone=!1,this._ignore=!1,this._hasWindow=!1,this._hasWindowByPass=!1,this._hasPresence=!1,this._hasMotion=!1,this._hasOverpowering=!1,this._hasAutoStartStop=!1,this._isAutoStartStopEnabled=!1,this._isAutoStartStopConfigured=!1,this._isLockConfigured=!1,this._isLocked=!1,this._hasLockCode=!1,this._oldValueMin=0,this._oldValueMax=0,this._display_bottom=0,this._display_top=0,this.modes=[],this.presets=[],this.safety_state={},this.powerInfos=[],this._externalPowerInfos=[],this.autoFanInfos=[],this.messages=[],this.displayMessages=!1,this._hasError=!1,this._renderingAsClassic=!1,this._showThemeMenu=!1,this._showClassicPopup=!1,this.theme="",this.isLocked=!1,this.isUserLocked=!1,this.isAutomationLocked=!1,this.showDigicodeModal=!1,this.enteredCode="",this.codeError=!1,this.isLocking=!1,this.timedPresetDuration=null,this.timedPresetActive=!1,this.timedPresetRemainingTime=null,this.timedPresetPreset=null,this._presetsPanelOpen=!1,this._regulationChartOpen=!1,this._presetTempEntities=[],this._handleKeyDown=t=>{t.key>="0"&&t.key<="9"?this._handleKeypadPress(t.key):"Backspace"===t.key&&this._handleKeypadClear()},this.render=()=>{var t,e,i,o,n;return(null===(t=this._config)||void 0===t?void 0:t.theme)===vr?(console.log("Rendering Gunmalmg theme"),nr(this)):B` `}constructor(){super(),this.value={},this._selectTargetTemperature="low",this.current=0,this.humidity=0,this.temperature=0,this.min=7,this.max=35,this.step=.5,this.powerPercent=0,this.meanCyclePower=0,this.valveOpenPercent=0,this.devicePower=0,this.regulatedTargetTemperature=null,this.isOn=!1,this.window=!1,this.windowByPass=!1,this.presence=!1,this.motion=!1,this.overpowering=!1,this.isDeviceActive=!1,this.isSleeping=!1,this.isRegulated=!1,this.isRecalculateScheduled=!1,this.windowState="off",this.windowAutoState="off",this.overpoweringState="off",this.presenceState="off",this.motionState="off",this.safetyState="off",this.status="loading",this.hvacMode=ur,this.hvacAction="idle",this.preset=hr,this.autoRegulationMode="",this.currentAutoFanMode=_r,this.autoFanMode=_r,this.fanMode="",this.hvacModeReason="",this.dragging=!1,this.name="",this.target="value",this._debouncedCallService=((t,e,i=!1)=>{let o;const a=(...a)=>{const n=i&&!o;clearTimeout(o),o=window.setTimeout((()=>{o=void 0,i||t(...a)}),e),n&&t(...a)};return a.cancel=()=>{clearTimeout(o)},a})((t=>this._callService(t)),1e3),this._init=!0,this._firstRender=!0,this._gunmalmgPresetScrollDone=!1,this._ignore=!1,this._hasWindow=!1,this._hasWindowByPass=!1,this._hasPresence=!1,this._hasMotion=!1,this._hasOverpowering=!1,this._hasAutoStartStop=!1,this._isAutoStartStopEnabled=!1,this._isAutoStartStopConfigured=!1,this._autoStartStopStopMode=xr,this._autoStartStopStopModeOptions=[],this._isAutoFanPlugin=!1,this._isAutoFanEnabled=!1,this._autoFanSelectedMode="",this._isLockConfigured=!1,this._isLocked=!1,this._hasLockCode=!1,this._oldValueMin=0,this._oldValueMax=0,this._display_bottom=0,this._display_top=0,this.modes=[],this.presets=[],this.safety_state={},this.powerInfos=[],this._externalPowerInfos=[],this.autoFanInfos=[],this.messages=[],this.displayMessages=!1,this._hasError=!1,this._renderingAsClassic=!1,this._showThemeMenu=!1,this._showClassicPopup=!1,this.theme="",this.isLocked=!1,this.isUserLocked=!1,this.isAutomationLocked=!1,this.showDigicodeModal=!1,this.enteredCode="",this.codeError=!1,this.isLocking=!1,this.timedPresetDuration=null,this.timedPresetActive=!1,this.timedPresetRemainingTime=null,this.timedPresetPreset=null,this._presetsPanelOpen=!1,this._regulationChartOpen=!1,this._presetTempEntities=[],this._autoStartStopEditMode=!1,this._handleKeyDown=t=>{t.key>="0"&&t.key<="9"?this._handleKeypadPress(t.key):"Backspace"===t.key&&this._handleKeypadClear()},this.render=()=>{var t,e,i,o,a;return(null===(t=this._config)||void 0===t?void 0:t.theme)===Tr?(console.log("Rendering Gunmalmg theme"),ar(this)):W`
<ha-card class=${bt({[this.hvacMode]:!0,locked:this.isUserLocked,"has-preset-mod":!!(null===(e=this._config)||void 0===e?void 0:e.allow_preset_modification),"has-regulation-chart":!!(null===(i=this._config)||void 0===i?void 0:i.show_regulation_chart)})} <ha-card class=${bt({[this.hvacMode]:!0,locked:this.isUserLocked,"has-preset-mod":!!(null===(e=this._config)||void 0===e?void 0:e.allow_preset_modification),"has-regulation-chart":!!(null===(i=this._config)||void 0===i?void 0:i.show_regulation_chart)})}
> >
${(null===(o=this._config)||void 0===o?void 0:o.disable_menu)?"":B` ${(null===(o=this._config)||void 0===o?void 0:o.disable_menu)?"":W`
<ha-icon-button <ha-icon-button
class="more-info" class="more-info"
.label=${this.hass.localize("ui.panel.lovelace.cards.show_more_info")} .label=${this.hass.localize("ui.panel.lovelace.cards.show_more_info")}
.path=${Tt} .path=${St}
@click=${this._toggleThemeMenu} @click=${this._toggleThemeMenu}
tabindex="0" tabindex="0"
></ha-icon-button> ></ha-icon-button>
${this._showThemeMenu?B` ${this._showThemeMenu?W`
<div class="menu-backdrop" @click=${this._closeThemeMenu}></div> <div class="menu-backdrop" @click=${this._closeThemeMenu}></div>
<div class="theme-menu"> <div class="theme-menu">
<div class="theme-menu-header"> <div class="theme-menu-header">
<div class="theme-menu-title" @click=${()=>{this._handleMoreInfo(),this._closeThemeMenu()}}>${_n({hass:this.hass,string:"editor.card.climate.menu_system"})}</div> <div class="theme-menu-title" @click=${()=>{this._handleMoreInfo(),this._closeThemeMenu()}}>${ma({hass:this.hass,string:"editor.card.climate.menu_system"})}</div>
</div> </div>
<div class="theme-menu-item" style="border-top:1px solid var(--divider-color, #e0e0e0);"></div> <div class="theme-menu-item" style="border-top:1px solid var(--divider-color, #e0e0e0);"></div>
${""} ${""}
${(null===(n=this._config)||void 0===n?void 0:n.theme)===vr?B` ${(null===(a=this._config)||void 0===a?void 0:a.theme)===Tr?W`
<div class="theme-menu-item" @click=${()=>{this._menuLockToggle(),this._closeThemeMenu()}}> <div class="theme-menu-item" @click=${()=>{this._menuLockToggle(),this._closeThemeMenu()}}>
${this._isLocked?_n({hass:this.hass,string:"extra_states.unlock"}):_n({hass:this.hass,string:"extra_states.lock"})} ${this._isLocked?ma({hass:this.hass,string:"extra_states.unlock"}):ma({hass:this.hass,string:"extra_states.lock"})}
</div> </div>
${this.timedPresetActive?B` ${this.timedPresetActive?W`
<div class="theme-menu-item" @click=${()=>{this._menuCancelTimedPreset(),this._closeThemeMenu()}}> <div class="theme-menu-item" @click=${()=>{this._menuCancelTimedPreset(),this._closeThemeMenu()}}>
${_n({hass:this.hass,string:"extra_states.cancel_timed_preset"})} ${ma({hass:this.hass,string:"extra_states.cancel_timed_preset"})}
</div> </div>
`:""} `:""}
`:""} `:""}
<div class="theme-menu-item" @click=${()=>this._applyTheme("classic")}>${_n({hass:this.hass,string:"editor.card.climate.theme_classic"})}</div> <div class="theme-menu-item" @click=${()=>this._applyTheme("classic")}>${ma({hass:this.hass,string:"editor.card.climate.theme_classic"})}</div>
<div class="theme-menu-item" @click=${()=>this._applyTheme("vtherm")}>${_n({hass:this.hass,string:"editor.card.climate.theme_vtherm"})}</div> <div class="theme-menu-item" @click=${()=>this._applyTheme("vtherm")}>${ma({hass:this.hass,string:"editor.card.climate.theme_vtherm"})}</div>
<div class="theme-menu-item" @click=${()=>this._applyTheme("uncolored")}>${_n({hass:this.hass,string:"editor.card.climate.theme_uncolored"})}</div> <div class="theme-menu-item" @click=${()=>this._applyTheme("uncolored")}>${ma({hass:this.hass,string:"editor.card.climate.theme_uncolored"})}</div>
<div class="theme-menu-item" @click=${()=>this._applyTheme("gunmalmg")}>${_n({hass:this.hass,string:"editor.card.climate.theme_gunmalmg"})}</div> <div class="theme-menu-item" @click=${()=>this._applyTheme("gunmalmg")}>${ma({hass:this.hass,string:"editor.card.climate.theme_gunmalmg"})}</div>
</div> </div>
`:""} `:""}
`} `}
@@ -1747,7 +1782,7 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
> >
<div class="dialog-content"> <div class="dialog-content">
<h2 class="dialog-title"> <h2 class="dialog-title">
${this.isLocking?_n({hass:this.hass,string:"extra_states.lock"}):_n({hass:this.hass,string:"extra_states.unlock"})} ${this.name} ${this.isLocking?ma({hass:this.hass,string:"extra_states.lock"}):ma({hass:this.hass,string:"extra_states.unlock"})} ${this.name}
</h2> </h2>
<div class="code-display ${this.codeError?"error":""}"> <div class="code-display ${this.codeError?"error":""}">
<span class="digit ${this.enteredCode.length>0?"filled":""}"></span> <span class="digit ${this.enteredCode.length>0?"filled":""}"></span>
@@ -1756,7 +1791,7 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
<span class="digit ${this.enteredCode.length>3?"filled":""}"></span> <span class="digit ${this.enteredCode.length>3?"filled":""}"></span>
</div> </div>
<div class="error-message ${this.codeError?"visible":""}"> <div class="error-message ${this.codeError?"visible":""}">
${_n({hass:this.hass,string:"extra_states.code_error"})} ${ma({hass:this.hass,string:"extra_states.code_error"})}
</div> </div>
<div class="keypad"> <div class="keypad">
@@ -1784,7 +1819,7 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
</div> </div>
</ha-dialog> </ha-dialog>
</ha-card> </ha-card>
`}}connectedCallback(){super.connectedCallback(),this._gunmalmgPresetScrollDone=!1}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("keydown",this._handleKeyDown)}static async getConfigElement(){return await Promise.resolve().then((function(){return Bb})),document.createElement("versatile-thermostat-ui-card-editor")}static async getStubConfig(t){const e=Object.keys(t.states).filter((t=>["climate"].includes(t.split(".")[0]))),i=e.filter((e=>{var i;return null===(i=t.states[e].attributes)||void 0===i?void 0:i.specific_states}));return{type:"custom:versatile-thermostat-ui-card",entity:i[0]||e[0]}}};function Tr(t){return t+.5|0}kr.styles=[s` `}}connectedCallback(){super.connectedCallback(),this._gunmalmgPresetScrollDone=!1}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("keydown",this._handleKeyDown)}static async getConfigElement(){return await Promise.resolve().then((function(){return Gb})),document.createElement("versatile-thermostat-ui-card-editor")}static async getStubConfig(t){const e=Object.keys(t.states).filter((t=>["climate"].includes(t.split(".")[0]))),i=e.filter((e=>{var i;return null===(i=t.states[e].attributes)||void 0===i?void 0:i.specific_states}));return{type:"custom:versatile-thermostat-ui-card",entity:i[0]||e[0]}}};function Pr(t){return t+.5|0}Ar.styles=[s`
:host { :host {
display: block; display: block;
box-sizing: border-box; box-sizing: border-box;
@@ -2170,6 +2205,28 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
color: var(--text-primary-color, #fff); color: var(--text-primary-color, #fff);
} }
.auto-start-stop-select {
height: 28px;
max-width: 120px;
border: 1px solid var(--divider-color, #e0e0e0);
border-radius: 4px;
padding: 0 4px;
font-size: 13px;
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
outline: none;
cursor: pointer;
transition: border-color 0.2s ease;
}
.auto-start-stop-select:focus {
border-color: var(--primary-color);
}
.auto-start-stop-select.active {
border-color: var(--primary-color);
}
.timed-preset-remaining { .timed-preset-remaining {
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
@@ -2258,6 +2315,12 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
width: 40px; width: 40px;
} }
.clickable-info-label {
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
#vt-control-buttons { #vt-control-buttons {
z-index: 0; z-index: 0;
position: absolute; position: absolute;
@@ -2805,10 +2868,10 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
} }
/* Column colors */ /* Column colors */
.preset-temp-col-label.col-frost { color: #3a9ff2; } .preset-temp-col-label.col-frost, .preset-temp-cell.preset-col-frost { color: #3a9ff2; }
.preset-temp-col-label.col-eco { color: #5dd461; } .preset-temp-col-label.col-eco, .preset-temp-cell.preset-col-eco { color: #5dd461; }
.preset-temp-col-label.col-comfort { color: #f9a21f; } .preset-temp-col-label.col-comfort, .preset-temp-cell.preset-col-comfort { color: #f9a21f; }
.preset-temp-col-label.col-boost { color: #f75252; } .preset-temp-col-label.col-boost, .preset-temp-cell.preset-col-boost { color: #f75252; }
.preset-col-frost .preset-step-btn { background: rgba(58,159,242,0.15); color: #3a9ff2; border-color: rgba(58,159,242,0.4); } .preset-col-frost .preset-step-btn { background: rgba(58,159,242,0.15); color: #3a9ff2; border-color: rgba(58,159,242,0.4); }
.preset-col-frost .preset-step-btn:hover { background: #3a9ff2; color: white; } .preset-col-frost .preset-step-btn:hover { background: #3a9ff2; color: white; }
@@ -2901,12 +2964,12 @@ const er=270;const ir=new Set(["ArrowRight","ArrowUp","ArrowLeft","ArrowDown","P
fill: var(--hvac-mode-color, #f44336); fill: var(--hvac-mode-color, #f44336);
} }
`,ar,sr],kr.additionalThemeStyles=[sr],t([ut({attribute:!1})],kr.prototype,"hass",void 0),t([ut({type:Number})],kr.prototype,"value",void 0),t([mt()],kr.prototype,"_selectTargetTemperature",void 0),t([ut({type:Number})],kr.prototype,"current",void 0),t([ut({type:Number})],kr.prototype,"humidity",void 0),t([ut({type:Number})],kr.prototype,"temperature",void 0),t([ut({type:Number})],kr.prototype,"min",void 0),t([ut({type:Number})],kr.prototype,"max",void 0),t([ut({type:Number})],kr.prototype,"step",void 0),t([ut({type:Number})],kr.prototype,"powerPercent",void 0),t([ut({type:Number})],kr.prototype,"meanCyclePower",void 0),t([ut({type:Number})],kr.prototype,"valveOpenPercent",void 0),t([ut({type:Number})],kr.prototype,"devicePower",void 0),t([ut({type:Number})],kr.prototype,"regulatedTargetTemperature",void 0),t([ut({type:Boolean})],kr.prototype,"isOn",void 0),t([ut({type:Boolean})],kr.prototype,"window",void 0),t([ut({type:Boolean})],kr.prototype,"windowByPass",void 0),t([ut({type:Boolean})],kr.prototype,"presence",void 0),t([ut({type:Boolean})],kr.prototype,"motion",void 0),t([ut({type:Boolean})],kr.prototype,"overpowering",void 0),t([ut({type:Boolean})],kr.prototype,"isDeviceActive",void 0),t([ut({type:Boolean})],kr.prototype,"isSleeping",void 0),t([ut({type:Boolean})],kr.prototype,"isRegulated",void 0),t([ut({type:Boolean})],kr.prototype,"isRecalculateScheduled",void 0),t([ut({type:String})],kr.prototype,"windowState",void 0),t([ut({type:String})],kr.prototype,"windowAutoState",void 0),t([ut({type:String})],kr.prototype,"overpoweringState",void 0),t([ut({type:String})],kr.prototype,"presenceState",void 0),t([ut({type:String})],kr.prototype,"motionState",void 0),t([ut({type:String})],kr.prototype,"safetyState",void 0),t([ut({type:String})],kr.prototype,"status",void 0),t([ut({type:String})],kr.prototype,"hvacMode",void 0),t([ut({type:String})],kr.prototype,"hvacAction",void 0),t([ut({type:String})],kr.prototype,"preset",void 0),t([ut({type:String})],kr.prototype,"autoRegulationMode",void 0),t([ut({type:String})],kr.prototype,"currentAutoFanMode",void 0),t([ut({type:String})],kr.prototype,"autoFanMode",void 0),t([ut({type:String})],kr.prototype,"fanMode",void 0),t([ut({type:String})],kr.prototype,"hvacOffReason",void 0),t([ut({type:Boolean,reflect:!0})],kr.prototype,"dragging",void 0),t([ut({type:String})],kr.prototype,"name",void 0),t([mt()],kr.prototype,"changingHigh",void 0),t([mt()],kr.prototype,"_hasError",void 0),t([mt()],kr.prototype,"_config",void 0),t([mt()],kr.prototype,"_showThemeMenu",void 0),t([mt()],kr.prototype,"_showClassicPopup",void 0),t([ut({type:String})],kr.prototype,"theme",void 0),t([mt()],kr.prototype,"isLocked",void 0),t([mt()],kr.prototype,"isUserLocked",void 0),t([mt()],kr.prototype,"isAutomationLocked",void 0),t([mt()],kr.prototype,"showDigicodeModal",void 0),t([mt()],kr.prototype,"enteredCode",void 0),t([mt()],kr.prototype,"codeError",void 0),t([mt()],kr.prototype,"isLocking",void 0),t([mt()],kr.prototype,"timedPresetDuration",void 0),t([mt()],kr.prototype,"timedPresetActive",void 0),t([mt()],kr.prototype,"timedPresetRemainingTime",void 0),t([mt()],kr.prototype,"timedPresetPreset",void 0),t([mt()],kr.prototype,"_presetsPanelOpen",void 0),t([mt()],kr.prototype,"_regulationChartOpen",void 0),t([mt()],kr.prototype,"_presetTempEntities",void 0),kr=t([ct("versatile-thermostat-ui-card")],kr);const Sr=(t,e,i)=>Math.max(Math.min(t,i),e);function Mr(t){return Sr(Tr(2.55*t),0,255)}function Dr(t){return Sr(Tr(255*t),0,255)}function Cr(t){return Sr(Tr(t/2.55)/100,0,1)}function Ar(t){return Sr(Tr(100*t),0,100)}const Pr={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},Er=[..."0123456789ABCDEF"],Lr=t=>Er[15&t],$r=t=>Er[(240&t)>>4]+Er[15&t],zr=t=>(240&t)>>4==(15&t);function Or(t){var e=(t=>zr(t.r)&&zr(t.g)&&zr(t.b)&&zr(t.a))(t)?Lr:$r;return t?"#"+e(t.r)+e(t.g)+e(t.b)+((t,e)=>t<255?e(t):"")(t.a,e):void 0}const Vr=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function Hr(t,e,i){const o=e*Math.min(i,1-i),n=(e,n=(e+t/30)%12)=>i-o*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]}function Rr(t,e,i){const o=(o,n=(o+t/60)%6)=>i-i*e*Math.max(Math.min(n,4-n,1),0);return[o(5),o(3),o(1)]}function Ir(t,e,i){const o=Hr(t,1,.5);let n;for(e+i>1&&(n=1/(e+i),e*=n,i*=n),n=0;n<3;n++)o[n]*=1-e-i,o[n]+=e;return o}function Nr(t){const e=t.r/255,i=t.g/255,o=t.b/255,n=Math.max(e,i,o),a=Math.min(e,i,o),s=(n+a)/2;let r,l,c;return n!==a&&(c=n-a,l=s>.5?c/(2-n-a):c/(n+a),r=function(t,e,i,o,n){return t===n?(e-i)/o+(e<i?6:0):e===n?(i-t)/o+2:(t-e)/o+4}(e,i,o,c,n),r=60*r+.5),[0|r,l||0,s]}function Fr(t,e,i,o){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,o)).map(Dr)}function Wr(t,e,i){return Fr(Hr,t,e,i)}function Br(t){return(t%360+360)%360}function jr(t){const e=Vr.exec(t);let i,o=255;if(!e)return;e[5]!==i&&(o=e[6]?Mr(+e[5]):Dr(+e[5]));const n=Br(+e[2]),a=+e[3]/100,s=+e[4]/100;return i="hwb"===e[1]?fu Line truncated `,nr,sr],Ar.additionalThemeStyles=[sr],t([pt({attribute:!1})],Ar.prototype,"hass",void 0),t([pt({type:Number})],Ar.prototype,"value",void 0),t([mt()],Ar.prototype,"_selectTargetTemperature",void 0),t([pt({type:Number})],Ar.prototype,"current",void 0),t([pt({type:Number})],Ar.prototype,"humidity",void 0),t([pt({type:Number})],Ar.prototype,"temperature",void 0),t([pt({type:Number})],Ar.prototype,"min",void 0),t([pt({type:Number})],Ar.prototype,"max",void 0),t([pt({type:Number})],Ar.prototype,"step",void 0),t([pt({type:Number})],Ar.prototype,"powerPercent",void 0),t([pt({type:Number})],Ar.prototype,"meanCyclePower",void 0),t([pt({type:Number})],Ar.prototype,"valveOpenPercent",void 0),t([pt({type:Number})],Ar.prototype,"devicePower",void 0),t([pt({type:Number})],Ar.prototype,"regulatedTargetTemperature",void 0),t([pt({type:Boolean})],Ar.prototype,"isOn",void 0),t([pt({type:Boolean})],Ar.prototype,"window",void 0),t([pt({type:Boolean})],Ar.prototype,"windowByPass",void 0),t([pt({type:Boolean})],Ar.prototype,"presence",void 0),t([pt({type:Boolean})],Ar.prototype,"motion",void 0),t([pt({type:Boolean})],Ar.prototype,"overpowering",void 0),t([pt({type:Boolean})],Ar.prototype,"isDeviceActive",void 0),t([pt({type:Boolean})],Ar.prototype,"isSleeping",void 0),t([pt({type:Boolean})],Ar.prototype,"isRegulated",void 0),t([pt({type:Boolean})],Ar.prototype,"isRecalculateScheduled",void 0),t([pt({type:String})],Ar.prototype,"windowState",void 0),t([pt({type:String})],Ar.prototype,"windowAutoState",void 0),t([pt({type:String})],Ar.prototype,"overpoweringState",void 0),t([pt({type:String})],Ar.prototype,"presenceState",void 0),t([pt({type:String})],Ar.prototype,"motionState",void 0),t([pt({type:String})],Ar.prototype,"safetyState",void 0),t([pt({type:String})],Ar.prototype,"status",void 0),t([pt({type:String})],Ar.prototype,"hvacMode",void 0),t([pt({type:String})],Ar.prototype,"hvacAction",void 0),t([pt({type:String})],Ar.prototype,"preset",void 0),t([pt({type:String})],Ar.prototype,"autoRegulationMode",void 0),t([pt({type:String})],Ar.prototype,"currentAutoFanMode",void 0),t([pt({type:String})],Ar.prototype,"autoFanMode",void 0),t([pt({type:String})],Ar.prototype,"fanMode",void 0),t([pt({type:String})],Ar.prototype,"hvacModeReason",void 0),t([pt({type:Boolean,reflect:!0})],Ar.prototype,"dragging",void 0),t([pt({type:String})],Ar.prototype,"name",void 0),t([mt()],Ar.prototype,"changingHigh",void 0),t([mt()],Ar.prototype,"_hasError",void 0),t([mt()],Ar.prototype,"_config",void 0),t([mt()],Ar.prototype,"_showThemeMenu",void 0),t([mt()],Ar.prototype,"_showClassicPopup",void 0),t([pt({type:String})],Ar.prototype,"theme",void 0),t([mt()],Ar.prototype,"isLocked",void 0),t([mt()],Ar.prototype,"isUserLocked",void 0),t([mt()],Ar.prototype,"isAutomationLocked",void 0),t([mt()],Ar.prototype,"showDigicodeModal",void 0),t([mt()],Ar.prototype,"enteredCode",void 0),t([mt()],Ar.prototype,"codeError",void 0),t([mt()],Ar.prototype,"isLocking",void 0),t([mt()],Ar.prototype,"timedPresetDuration",void 0),t([mt()],Ar.prototype,"timedPresetActive",void 0),t([mt()],Ar.prototype,"timedPresetRemainingTime",void 0),t([mt()],Ar.prototype,"timedPresetPreset",void 0),t([mt()],Ar.prototype,"_presetsPanelOpen",void 0),t([mt()],Ar.prototype,"_regulationChartOpen",void 0),t([mt()],Ar.prototype,"_presetTempEntities",void 0),t([mt()],Ar.prototype,"_autoStartStopEditMode",void 0),Ar=t([dt("versatile-thermostat-ui-card")],Ar);const Er=(t,e,i)=>Math.max(Math.min(t,i),e);function Lr(t){return Er(Pr(2.55*t),0,255)}function $r(t){return Er(Pr(255*t),0,255)}function zr(t){return Er(Pr(t/2.55)/100,0,1)}function Or(t){return Er(Pr(100*t),0,100)}const Vr={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},Hr=[..."0123456789ABCDEF"],Ir=t=>Hr[15&t],Rr=t=>Hr[(240&t)>>4]+Hr[15&t],Fr=t=>(240&t)>>4==(15&t);function Nr(t){var e=(t=>Fr(t.r)&&Fr(t.g)&&Fr(t.b)&&Fr(t.a))(t)?Ir:Rr;return t?"#"+e(t.r)+e(t.g)+e(t.b)+((t,e)=>t<255?e(t):"")(t.a,e):void 0}const jr=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function Wr(t,e,i){const o=e*Math.min(i,1-i),a=(e,a=(e+t/30)%12)=>i-o*Math.max(Math.min(a-3,9-a,1),-1);return[a(0),a(8),a(4)]}function Br(t,e,i){const o=(o,a=(o+t/60)%6)=>i-i*e*Math.max(Math.min(a,4-a,1),0);return[o(5),o(3),o(1)]}function Ur(t,e,i){const o=Wr(t,1,.5);let a;for(e+i>1&&(a=1/(e+i),e*=a,i*=a),a=0;a<3;a++)o[a]*=1-e-i,o[a]+=e;return o}function Yr(t){const e=t.r/255,i=t.g/255,o=t.b/255,a=Math.max(e,i,o),n=Math.min(e,i,o),s=(a+n)/2;let r,l,c;return a!==n&&(c=a-n,l=s>.5?c/(2-a-n):c/(a+n),r=function(t,e,i,o,a){return t===a?(e-i)/o+(e<i?6:0):e===a?(i-t)/o+2:(t-e)/o+4}(e,i,o,c,a),r=60*r+.5),[0|r,l||0,s]}function qr(t,e,i,o){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,o)).map($r)}function Zr(t,e,i){return qr(Wr,t,e,i)}function Xr(t){return(t%360+360)%360}function Kr(t){const e=jr.exec(t);let i,o=255;if(!e)return;e[5]!==i&&(o=e[6]?Lr(+e[5]):$r(+e[5]));const a=Xr Line truncated
<ha-form <ha-form
.hass=${this.hass} .hass=${this.hass}
.data=${a} .data=${n}
.schema=${n} .schema=${a}
.computeLabel=${this._computeLabel} .computeLabel=${this._computeLabel}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></ha-form> ></ha-form>
`}_valueChanged(t){const e=t.detail.value,{section_all_themes:i,section_classic_only:o}=e,n=function(t,e){var i={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&e.indexOf(o)<0&&(i[o]=t[o]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(o=Object.getOwnPropertySymbols(t);n<o.length;n++)e.indexOf(o[n])<0&&Object.prototype.propertyIsEnumerable.call(t,o[n])&&(i[o[n]]=t[o[n]])}return i}(e,["section_all_themes","section_classic_only"]),a=Object.assign(Object.assign(Object.assign({},n),i||{}),o||{});a.theme||(a.theme="classic"),Tn(this,"config-changed",{config:a}),Tn(this,"hass",{config:a})}};Wb.ALL_THEMES_KEYS=["disable_name","disable_safety_warning","set_current_as_main","allow_lock_toggle","disable_timed_preset","use_manual_duration_input","allow_preset_modification","show_regulation_chart"],Wb.CLASSIC_ONLY_KEYS=["disable_window","disable_autoStartStop","disable_overpowering","disable_heat","disable_cool","disable_heat_cool","disable_auto","disable_dry","disable_fan_only","disable_off","disable_sleep","disable_menu","disable_buttons","disable_power_infos","disable_auto_fan_infos","disable_target_icon","disable_presets","show_status_text","show_background_gradient_on_active"],t([mt()],Wb.prototype,"_config",void 0),t([ut({attribute:!1})],Wb.prototype,"hass",void 0),Wb=Hb=t([ct("versatile-thermostat-ui-card-editor")],Wb);var Bb=Object.freeze({__proto__:null,get ClimateCardEditor(){return Wb}});export{kr as VersatileThermostatUi,yr as registerCustomCard}; `}_valueChanged(t){const e=t.detail.value,{section_all_themes:i,section_classic_only:o}=e,a=function(t,e){var i={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&e.indexOf(o)<0&&(i[o]=t[o]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var a=0;for(o=Object.getOwnPropertySymbols(t);a<o.length;a++)e.indexOf(o[a])<0&&Object.prototype.propertyIsEnumerable.call(t,o[a])&&(i[o[a]]=t[o[a]])}return i}(e,["section_all_themes","section_classic_only"]),n=Object.assign(Object.assign(Object.assign({},a),i||{}),o||{});n.theme||(n.theme="classic"),ka(this,"config-changed",{config:n}),ka(this,"hass",{config:n})}};Kb.ALL_THEMES_KEYS=["disable_name","disable_safety_warning","set_current_as_main","allow_lock_toggle","disable_timed_preset","use_manual_duration_input","allow_preset_modification","show_regulation_chart"],Kb.CLASSIC_ONLY_KEYS=["disable_window","disable_autoStartStop","disable_overpowering","disable_heat","disable_cool","disable_heat_cool","disable_auto","disable_dry","disable_fan_only","disable_off","disable_sleep","disable_menu","disable_buttons","disable_power_infos","disable_auto_fan_infos","disable_target_icon","disable_presets","show_status_text","show_background_gradient_on_active"],t([mt()],Kb.prototype,"_config",void 0),t([pt({attribute:!1})],Kb.prototype,"hass",void 0),Kb=Ub=t([dt("versatile-thermostat-ui-card-editor")],Kb);var Gb=Object.freeze({__proto__:null,get ClimateCardEditor(){return Kb}});export{Ar as VersatileThermostatUi,Mr as registerCustomCard};